几种常用的排序算法

几种常用的排序算法

冒泡排序

最好时间复杂度O(n),最坏时间复杂度O(n^2),平均时间复杂度O(n^2)
基本理论:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个
  2. 每趟从第一对相邻元素开始,对每一对相邻元素作同样的工作,直到最后一对
  3. 针对所有的元素重复以上的步骤,除了已排序过的元素(每趟排序后的最后一个元素),直到没有任何一对数字需要比较
void bubble(int *array, int n)    
{    
        for (size_t i = 0; i < n-1; i++) {    
                if (*(array+i) > *(array+i+1))    
                        swapInt(array+i, array+i+1);
        }    
}    
    
void bubbleSort(int *array, int n)    
{    
        for (size_t i = n; i > 0; i--) {    
                bubble(array, i);
        }    
}

冒泡排序算法的优化,判断本次循环是否有交换,要是没有交换,则说明以及是数组是顺序的,不需要继续判断。

void bubbleSortOptimization(int *array, int n)
{
        int isSwap = 0;
        for (size_t j = n-1; j > 0; j--) {
                isSwap = 0;
                for (size_t i = 0; i < j; i++) {
                        if (*(array+i) > *(array+i+1)) {
                                swapInt(array+i, array+i+1);
                                array+i+1                                        
                                isSwap = 1;
                        }
                }
                if (!isSwap)
                        break;
        }
}

继续对冒泡排序继续优化,保存每次小循环最后一次最后一个位置,该位置之后都是有序的,不需要排序后面的数字

void bubbleSortOptimization1(int *array, int n)
{
        int pos = n-1;
        int isSwap = 0;
        for (size_t j = n-1; j > 0; j--) {
                isSwap = 0;
                int newPos = 0;
                for (size_t i = 0; i < pos; i++) {
                        if (*(array+i) > *(array+i+1)) {
                                swapInt(array+i, array+i+1);
                                isSwap = 1;
                                newPos = i;
                        }
                }
                if (!isSwap)
                        break;  
                pos = newPos;
        }
}

选择排序

最好时间复杂度O(n^2),最坏时间复杂度O(n^2),平均时间复杂度O(n^2)
基本理论:

  1. 首先在未排序序列中找到最大元素,存放到排序序列的最后位置
  2. 再从剩余未排序元素中继续寻找最大元素,然后放到未排序序列的最后位置
  3. 重复第二步,直到所有元素均排序完毕
int findMaxPos(int *array, int n)
{
        int pos = 0;
        int max = array[0];
        for (size_t i = 1; i < n; i++) {
                if (array[i] > max) {
                        max = array[i];
                        pos = i;
                }
        }
        return pos;
}

void selectSort(int *array, int n)
{
        while (n > 1) {
                int pos = findMaxPos(array, n);
                swapInt(array+n-1, array+pos);
                n--;
        }
}

选择排序的排序,在一次遍历中同时找出最大值和最小值,放到数组两端,这样就能将遍历的趟数减少一半

void selectionSortOptimize(int * num, int size)
{
    int left = 0, right = size - 1;

    while (left < right){
        int min = left, max = right;
        for (size_t i = left; i <= right; i++){ //内循环同时找出最大值和最小值
            if(num[i] < num[min])
                min = i;
            if(num[i] > num[max])
                max = i;
        }
        swapInt(&num[max], &num[right]);
        swapInt(&num[min], &num[left]);
        
        left++;
        right--;
    }
    return ;
}

插入排序

最好时间复杂度O(n),最坏时间复杂度O(n^2),平均时间复杂度O(n^2)
基本思想:将无序数组中的数据插入到有序数组中合适的位置。

void insert(int *array, int n)
{
        int i = n;
        int key = array[n];             //设置一个key保留

        while (array[i-1] > key){
                array[i] = array[i-1];  //数字是向后移动的
                i--;
                if (0 == i)
                        break;
        }
        array[i] = key;
}

void insertSort(int *array, int n)
{
        for (size_t i = 1; i < n; i++) {
                insert(array, i); ‣n: i                                                                                       
        }
}

快速排序

最好时间复杂度O(nlog2n),最坏时间复杂度O(n^2),平均时间复杂度O(nlog2n)

  1. 先从数列中取出一个数作为基准数
  2. 将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边
  3. 再对左右区间重复第二步,直到各区间只有一个数
void qSort(int *array, int begin, int end)
{
        if (begin>end)
                return;
                
        int key = array[begin];
        int i = begin, j = end;

        while (i < j) {
                /*从右往左找到第一个比key小的数值*/
                while (i<j && *(array+j) >= key) 
                        j--;
                        
                /*从左往右找到第一个比key大的数值*/
                while (i<j && *(array+i) <= key) 
                        i++;
                        
                swapInt(array+i, array+j);      //交换两者的大小 
        }//循环跳出来时i和j指向同一个位置,此时key左面的都比key小,key右面的都比key大
        swapInt(array+begin, array+j);  //此时i或者j的位置就是基准值应该放的位置,交换     
        
        qSort(array, begin, i-1); ‣end: i-1                                                                                   
        qSort(array, i+1, end); ‣begin: i+1                                                                                   
        return;
}

二分查找算法

查找的前提是数组以及拍好序了

int binarySearch(int *array, int key, int low, int high)
{
        while (low<=high) {
                int mid = (low+high)/2;
                if (key == *(array+mid)) {
                        return mid;
                }else if (key > *(array+mid)) {
                        low = mid+1;
                }else {
                        high = mid-1;
                }
        }

        return -1;
}

int binarySearch_recursive(int *array, int key, int low, int high)
{
        if (low > high)
                return -1;      

        int mid = low+(high-low)/2;
        if (*(array+mid) == key) {
                return mid;
        }else if (*(array+mid) > key) {
                return binarySearch_recursive(array, key, low, mid-1);
        }else {
                return binarySearch_recursive(array, key, mid+1, high);
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值