常用排序算法总结

在面试或者数据结构相关的考试中,经常会被要求到的算法主要有插入排序、冒泡排序、归并排序和快速排序。对这几种算法,不但应该知道其原理或者过程,还应该对他们的各种特性了然于胸,从最好、最差、平均时间空间复杂度等方面对比其优劣。在面试中这几种排序算法也会经常作为手写代码能力的考量,所以应该要求自己对这几种算法的代码信手拈来。所以在此把几种算法详细记录一下。

冒泡排序

/***********冒泡排序************
空间复杂度:O(1)
时间复杂度:有序的时候最好情况为O(n),最坏和平均为O(n^2)
稳定性:稳定
*/
void bubbleSort(int *arr, int n){
    for(int i = 1; i<n; i++){
        int j = i-1;
        while(j>=0){
            if(arr[j] > arr[j+1]){
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
                j--;
            }
            else break;//本趟遍历没有发生交换
        }
    }
}

快排

//http://blog.csdn.net/morewindows/article/details/6684558 挖坑排序
void quick_sort(int s[], int l, int r)  
{  
    if (l < r)  
    {  
        
        int i = l, j = r, x = s[l];  
        while (i < j)  
        {  
            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数  
                j--;    
            if(i < j)   
                s[i++] = s[j];  
              
            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数  
                i++;    
            if(i < j)   
                s[j--] = s[i];  
        }  
        s[i] = x;  
        quick_sort(s, l, i - 1); // 递归调用   
        quick_sort(s, i + 1, r);  
    }  
}  

插入排序

/***********折半插入排序*************
相对于直接插入排序,它在查找的时候用
折半查找,减少了比较的次数,但是移动
的次数不变,还是n平方
空间复杂度:O(1)
时间复杂度:O(n^2)
稳定性:稳定
************************************/
void insertSortBi(int *arr, int n){
    int i, j, low, mid, high;
    for(i = 2; i<=n; i++){
        arr[0] = arr[i];//arr[0]为哨兵,不存放元素
        low = 1; high = i-1;        
        //折半查找,减少了比较次数
        while(low <= high){
            mid = (low+high)/2;
            if(arr[mid] > arr[0]) high = mid-1;
            else low = mid + 1;
        }

        //向后移动元素
        for(j = i-1; j>=high+1; --j)
            arr[j+1] = arr[j];
        
        arr[high+1] = arr[0];
    }

    //打印元素
    //for(int k = 0; k<6; k++)
        //cout<<arr[k]<<endl;
}

堆排序

//从i节点开始调整,从0开始计数,len为节点总数
void MinHeapFixdown(int a[], int i, int n)  
{  
    int j, temp;  
  
    temp = a[i];  
    j = 2 * i + 1;  
    while (j < n)  
    {  
        if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的  
            j++;  
  
        if (a[j] >= temp)  
            break;  
  
        a[i] = a[j];     //把较小的子结点往上移动,替换它的父结点  
        i = j;  
        j = 2 * i + 1;  
    }  
    a[i] = temp;  
} 

//构建小根堆
void buildMinHeap(int arr[], int len)
{
    for(int i = len/2-1; i>=0; i--)
        //把第i个元素向下调整(如果大于子节点的话)
        MinHeapFixdown(arr, i, len);
}

/***********堆排序*******
堆排序需要先对线性表中的元素构建堆,然后根据堆的性质,
输出堆顶元素,然后对输出堆顶后被破坏的堆重新调整为堆,
如此重复,直到堆中仅剩下一个元素位置
空间复杂度:O(1)
时间复杂度:最好最坏和平均情况下都为O(nlogn)
稳定性:不稳定
*/
void heapSort(int arr[], int n)
{
    //构建小根堆,小根堆的排序后是从大到小的顺序
    buildMinHeap(arr, n);
    for(int i = n-1; i>0; i--){
        swap(arr[i], arr[0]);
        MinHeapFixdown(arr, 0, i);
    }
}

转载于:https://www.cnblogs.com/mooba/p/6558032.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值