算法---冒泡排序,快速排序,二分查找(折半查找),选择排序,插入排序

好久没有记录东西了,今天整理记录一些常用的算法

时间复杂度:算法运行的时间
空间复杂度:算法运行完所需内存的大小
是不是稳定的算法:根据排序是相同的数据会不会被移动
 
一.冒泡排序
 
1.什么是冒泡排序?
答:冒泡排序算法的运作如下:(从后往前)
 
  1. 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 3.针对所有的元素重复以上的步骤,除了最后一个。
  4. 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
 
2.时间复杂度 和 空间复杂度
冒泡排序的时间复杂度:O(n2) 
冒泡排序的空间复杂度:O(1)
 
3.代码

NSMutableArray * array = [NSMutableArray arrayWithObjects: @"1",@"8",@"2",@"7",@"2",@"5",@"9",nil];

    //选择

        for (int  i =0; i<[array count]-1; i++) {

            for (int j = i+1; j<[array count]; j++) {

                if ([array[i] intValue]>[array[j] intValue]) {

                 //交换

            [array exchangeObjectAtIndex:i withObjectAtIndex:j];

                }

            }

        }

        NSLog(@"%@",array);

 
4.是否是稳定算法:是
 
       
 
 
 
二.快速排序———》递归
 
1.什么是快速排序?
答:设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序
一趟快速排序的算法是:
  1. 1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
    2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
    3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
    4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
    5)重复第3、4步,直到i=j;
  2.        6)然后,对k两边的数据,再分组分别进行上述的过程,直到不能再分组为止
注意:第一遍快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。为了得到最后结果,需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。
 
2.时间复杂度 和 空间复杂度
快速排序的时间复杂度:O(n2) 
快速排序的空间复杂度:O(log 2 N)~O(log n)
3.代码
- (void)quickSortArray:(NSMutableArray *)array withLeftIndex:(NSInteger)leftIndex andRightIndex:(NSInteger)rightIndex
{
    if (leftIndex >= rightIndex) {//如果数组长度为0或1时返回
        return ;
    }
   
    NSInteger i = leftIndex;
    NSInteger j = rightIndex;
    //记录比较基准数
    NSInteger key = [array[i] integerValue];
   
    while (i < j) {
        /**** 首先从右边j开始查找比基准数小的值 ***/
        while (i < j && [array[j] integerValue] >= key) {//如果比基准数大,继续查找
            j--;
        }
        //如果比基准数小,则将查找到的小值调换到i的位置
        NSNumber *temp = array[i];
        array[i] = array[j];
        array[j] = temp;
        NSLog(@"%@",array);
        /**** 当在右边查找到一个比基准数小的值时,就从i开始往后找比基准数大的值 ***/
        while (i < j && [array[i] integerValue] <= key) {//如果比基准数小,继续查找
            i++;
        }
        //如果比基准数大,则将查找到的大值调换到j的位置
        NSNumber *bigTemp = array[j];
        array[j] = array[i];
        array[i] = bigTemp;
        NSLog(@"%@",array);
    }
   
    //将基准数放到正确位置
    array[i] = @(key);
   
    /**** 递归排序 ***/
    //排序基准数左边的
    [self quickSortArray:array withLeftIndex:leftIndex andRightIndex:i - 1];
    //排序基准数右边的
    [self quickSortArray:array withLeftIndex:i + 1 andRightIndex:rightIndex];
}
 
4.是否是稳定算法:否
 
 
 
三. 二分查找(折半查找)
 
折半查找方法适用于不经常变动而查找频繁的有序列表
 
 
1.什么是 二分查找?
答:给一个数,要求查找出来,前提这个数组是一个升序的数组,取数组的中间值,与此数比较,若相等,则返回这个数,若找的数比中间数小,则在中间数的左侧中再找,放在再右侧找,知道找到为止。
一趟快速排序的算法是:
  1. 1)数组为有序
    2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
    3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
    4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
    5)重复第3、4步,直到i=j;
  2.        6)然后,对k两边的数据,再分组分别进行上述的过程,直到不能再分组为止
注意:第一遍快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。为了得到最后结果,需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。
 
2.时间复杂度 和 空间复杂度
二分查找的时间复杂度:O(log n) 
快速排序的空间复杂度:O(1)
3.代码
-(NSInteger)searchNumWithArray:(NSArray *)array Num:(int)num
{
    if (array.count <= 0) {
        return -1;
    }
    int low = 0;
    int height = (int)array.count - 1;
    while (low <= height) {
        int middle = (height - low)/2 + low;

    if (num == [array[middle] integerValue]) {
        return middle;
    }else if (num < [array[middle] integerValue]){
       
        return middle-1;
    }else{
    
        return middle+1;
    }
    }
   
    return -1;
}
 
 
 
四. 选择排序
 
1.什么是选择排序?
答:每次找到最小的数才会交换
   2, 1, 5, 4, 9
  第一次排序:1, 2, 5, 4, 9
  第二次排序: 1, 2, 5, 4, 9
  第三次排序: 1, 2, 4, 5, 9
  第四次排序: 1, 2, 4, 5, 9
 
 
(1)每次排序的时候都需要寻找第n小的数据,并且和array[n-1]发生交换
(2)等到n个数据都排序好,那么选择排序结束。
 
2.时间复杂度 和 空间复杂度
选择排序的时间复杂度:O(n 2) 
选择排序的空间复杂度:O(1)
3.代码
- (NSMutableArray *)SelectSortOC:(NSMutableArray *)arr
{
    for (int i=0; i < [arr count]-1; i++) {
        for (int j = i+1; j<[arr count]; j++)               {
            if ([arr[i] integerValue] > [arr[j] integerValue]) {
                [arr exchangeObjectAtIndex:i withObjectAtIndex:j];
            }
        }
       
    }
    return arr;
}
4.是否是稳定算法:否
 
 
 
五. 插入排序
 
1.什么是插入排序?
答:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
 
2.时间复杂度 和 空间复杂度
插入排序的时间复杂度:O(n 2) 
插入排序的空间复杂度:O(1)
3.代码
- (NSMutableArray *)InsertSortOC:(NSMutableArray *)arr
{
    for (int i=1; i < [arr count]; i++) {
        for (int j=0; j < i ; j++) {
            if ([arr[i] integerValue] < [arr[j] integerValue]) {
                [arr exchangeObjectAtIndex:i withObjectAtIndex:j];
            }
        }
    }
    return arr;
}
 
4.是否是稳定算法:是
原文地址:https://www.cnblogs.com/miaomiaocat/p/6398264.html