常用的七大排序

十大排序

https://zhuanlan.zhihu.com/p/172524701

冒泡排序

  • 解释:
    相邻的两个值把最大的值放在右边,最小值放在左边,一次循环确定最后一个位置,逐层递进
  • 代码
    //十大排序之冒泡排序
    //升序
    void bubble(vector<int>& ans) {
        if(ans.empty() || ans.size() == 1) {
            return;
        }
        int size = ans.size();
        int change;
        for(int i = 1; i < size; i++) {
            for(int j = 1; j <= size - i; j++) {
                if(ans[j - 1] > ans[j]) {
                    change = ans[j - 1];
                    ans[j - 1] = ans[j];
                    ans[j] = change;
                }
            }
        }
    }
    

选择排序

  • 解释:
    从第一个位置寻找之后位置的最小值,将其和第一个值换位,然后逐层递进
  • 代码
    //十大排序之选择排序
    //升序
    void SelectSorte(vector<int>& ans) {
        int size = ans.size();
        int change;
        for(int i = 0; i < size; i++) {
            pair<int, int> m(i,ans[i]);
            for(int j = i; j < size; j++) {
                if(ans[j] < m.second) {
                    m.first = j;
                    m.second = ans[j];
                }
            }
            change = ans[m.first];
            ans[m.first] = ans[i];
            ans[i] = change;
        }
    }
    

插入排序

  • 解释:
    位置i开始(i之前都是按照升序排好的),将位置i的数在0-i之间找一个位置放下它,
  • 代码
    //十大排序之插入排序
    //升序
    void InsertSorte(vector<int>& ans) {
        int size = ans.size();
        int change;
        for(int i = 0; i < size; i++) {
            // for(int j = i; j >= 1 ; j--) {
            //     if(ans[j - 1] > ans[j]) {
            //         change = ans[j - 1];
            //         ans[j - 1] = ans[j];
            //         ans[j] = change;
            //     }
            // }
            for(int j = i; j >= 1 && ans[j - 1] > ans[j]; j--) {
                change = ans[j - 1];
                ans[j - 1] = ans[j];
                ans[j] = change;
            }
        }
    }
    

希尔排序

  • 解释:
    希尔排序是一种改善的插入排序,每次取间隔gap的大小分为一组,在组内进行插入排序,最后gap一定是等于1,那么就是间隔1进行插入排序有,就是一般的插入排序了
    它的时间复杂度首次突破O(n2),平均的是O(n1.3),但是最坏的情况还是O(n^2)

  • 代码

    int shellSorte(vector<int>& ans) {
        int flag = 0;
        int change;
        int size = ans.size();
        int gap = size/2;
        while (gap >= 1)
        {
            for(int i = gap; i < size; i++) {
                for(int j = i; j >= gap && ans[j - gap] > ans[j]; j -= gap) {
                    change = ans[j - gap];
                    ans[j - gap] = ans[j];
                    ans[j] = change;
                    flag++;
                }
            }
            
            gap = gap/2;
        }
        return flag;
    }
    
  • 和一般的插入比较:(分别比较一般的插入排序和希尔排序循环次数对比)
    输入数据是

     vector<int> ans1 = {22,8,9,1,7,2,3,5,4,6,0,23,10};
        vector<int> ans2 = {22,8,9,1,7,2,3,5,4,6,0,23,10};
    

归并排序

  • 解释:
    我们已知排序两个已知的有序数组的方法是使用双指针,我们怎么把一个数组分成有序的数组呢,就是一步一步分下来分成单个元素,那不就是有序的吗,之后再治之(也就是排序)

  • 代码

    int flag;
    void MergeSort(vector<int>& ans, int begin, int end) {
        if(begin >= end) {
            return;
        }
        //我们需要做的是分而治之,以下的递归做的是分
        int mid = (begin + end) >> 1;
        MergeSort(ans, begin, mid);
        MergeSort(ans, mid + 1, end);
    
        //至此,分的操作已经完成,要开始的是治(也就是排序)
        int begin1 = begin, end1 = mid, begin2 = mid + 1, end2 = end;
        //将两个数组的数据进行合并
        vector<int> temp;
        while(begin1 <= end1 && begin2 <= end2) {
            temp.push_back(ans[begin1] > ans[begin2] ? ans[begin2++] : ans[begin1++]);
        }
        while(begin1 <= end1) {
            temp.push_back(ans[begin1++]);
        }
        while(begin2 <= end2) {
            temp.push_back(ans[begin2++]);
        }
        cout << "第" << flag++ << "次合并" << endl;
        for(int i = begin; i <= end; i++) {
            ans[i] = temp[i - begin];
            cout << ans[i] << " ";
        }
        cout << endl;
        cout << "************************************" << endl;
    
    }
    
  • 分治的过程
    我们需要排序的数组是

    vector<int> ans = {8,9,1,7,2,3,5,4,6};
    

快速排序

  • 解释:
    选择一个位置作为标杆,之后用双指针得到以标杆为中心的一个数组,标杆之前为小于标杆的数,标杆之后为大于标杆的数,之后递归往下
  • 代码
    //十大排序之快速排序
    //升序
    
    
    void quickSort(vector<int>& arr, int start, int end) {
        if (start >= end) {
            return;
        }
        int flag = arr[end];//选取最后一位作为标杆
        int left = start, right = end - 1;
        //使用双指针来实现从大到小的排序(最好用草稿本写以下就知道了)
        while (left < right) {
            //注意以下循环的顺序,先进行的是left,之后才是right,所以最后在确定flag的位置的时候很重要
            while (arr[left] < flag && left < right) left++;     //                     ^
            while (arr[right] >= flag && left < right) right--;  //                     |
            std::swap(arr[left], arr[right]);                    //                     |
        }                                                        //                     |
        if (arr[left] >= arr[end])                               //                     |
            std::swap(arr[left], arr[end]);                      //                     |
        else                                                      //                    |
            left++;                     //left的位置为什么要++,因为 ---------------------
        quickSort(arr, start, left - 1);
        quickSort(arr, left + 1, end);
    }
    

堆排序

  • 解释:
    首先第一步是先建立一个大顶堆(或者小顶堆),之后通过交换首尾的位置,下沉尾部的目的达到排序的目的
  • 代码
//十大排序之堆排序
//大顶堆

//维护堆的性质,用于建立大顶堆
void heapidf(vector<int>& ans, int size, int i) {
    
    int parent = i;
    int lson = 2*i + 1;
    int rson = 2*i + 2;

    if(lson < size && ans[parent] < ans[lson]) {
        parent = lson;
    }
    if(rson < size && ans[parent] < ans[rson]) {
        parent = rson;
    }
    //说明此时需要交换
    if(parent != i) {
        swap<int>(ans[parent], ans[i]);
        heapidf(ans, size, parent);
    }
}

//排序入口
void heapsort(vector<int>& ans) {
    int size = ans.size();
    
    for(int i = size-1; i >= 0; i--) {
        heapidf(ans, size,i);
    }
    //到此处为止已经建立好了大顶堆了,之后要进行堆排序
    //原来的 ans = {6, 6, 8, 9, 9, 1, 7, 2, 3, 5, 4};
    //现在的 ans = {9, 9, 8, 6, 6, 1, 7, 2, 3, 5, 4};
    for(int i = size - 1; i >= 0; i--) {
        //排序的步骤为,先交换首尾的位置
        swap<int>(ans[i], ans[0]);
        //之后将尾部(此时的尾部到了首部的位置)沉下去
        heapidf(ans, i, 0);
    }
}
posted @ 2023-10-06 13:27  铜锣湾陈昊男  阅读(38)  评论(0)    收藏  举报