排序问题及算法

排序问题及算法

冒泡排序(Bubble-Sort)

  • 排序问题描述:

    输入:n个数的一个序列 $ {a_1,a_2,\ldots,a_n} $。

    输出:输入序列的一个排列 { a 1 ′ , a 2 ′ , … , a n ′ } \{a_1',a_2',\ldots,a_n'\} {a1,a2,,an},满足 $ a_1’\leq a_2’\leq\ldots\leq a_n’$。

  • 冒泡排序是一种流行但低效的排序算法,它的作用是反复交换相邻的未按次序排列的元素。

  • 代码:时间复杂度 O ( n 2 ) O\big(n^2\big) O(n2)

    void BubbleSort(int* A){
        int temp;
        for(int i=0; i<sizeof(A)/sizeof(int) ; ++i)){
            for(int j=0; j<sizeof(A)/sizeof(int) ; ++j)){
                if(A[j]<A[j-1]){
                    temp=A[j];
                    A[j]=A[j-1];
                    A[j-1]=temp;
                }
            }
        }
        return;
    }
    

插入排序(Insertion-Sort)

  • 排序问题描述:

    输入:n个数的一个序列 $ {a_1,a_2,\ldots,a_n} $。

    输出:输入序列的一个排列 { a 1 ′ , a 2 ′ , … , a n ′ } \{a_1',a_2',\ldots,a_n'\} {a1,a2,,an},满足 $ a_1’\leq a_2’\leq\ldots\leq a_n’$。

  • 流程:从第二个数向后面遍历,每次遍历将此数作为 k e y key key并与前面的数进行比对,若前面的数大于 k e y key key,则交换两数,直到数 k e y key key到达合适的位置。

  • 代码:时间复杂度 O ( n 2 ) O\big(n^2\big) O(n2)

    void InsertSort(int* arr){
        int key,i;
    	for(int j=2; j<sizeof(arr)/sizeof(int) ; ++j){
            key=arr[j];
            // Insert arr[j] into the sorted sequence arr[1...j-1].
            i=j-1;
            while(i>0 && arr[i]>key){
                arr[i+1]=arr[i];
                --i;
            }
            arr[i+1]=key;
        }
    }
    
  • 应用:

  1. 重写 I n s e r t S o r t ( ) InsertSort() InsertSort()函数,使之按降序排序:

    void InsertSort_Desc(int* arr){
    	for(int j=2; j<sizeof(arr)/sizeof(int) ; ++j){
            int key,i;
            key=arr[j];
            i=j-1;
            while(i>0 && arr[i]<key){//Only change '<'
                arr[i+1]=arr[i];
                --i;
            }
            arr[i+1]=key;
        }
    }
    
  2. 考虑两个 n n n位二进制整数相加:

    输入:两整数分别存在两个 n n n元数组 A A A B B B中;

    输出:将相加后的和按二进制存储在一个 ( n + 1 ) (n+1) (n+1)元数组 C C C中。

    写出代码:

    int* BinaryAdd(int* A, int* B){
    	if(sizeof(A)!=sizeof(B)){
            std::cout << "Error!" << std::endl;
            return nullptr;
        }
        int n=sizeof(A)/sizeof(int);
        int* C=new int[n+1];
        int carry=0;
        for(int i=0; i<n ;++i){
            C[i]=(A[i]+B[i]+carry)%2;
            carry=(A&&B)||((A||B)&&C);
        }
        C[n]=carry;
        return C;
    }
    

归并排序(Merge-Sort)

  • 归并排序算法完全遵循分治模式。直观上其操作如下:

    分解:分解待排序的 n n n个元素的序列成各具 n / 2 n/2 n/2个元素的两个子序列。

    解决:使用归并排序递归地排序两个子序列。

    合并:合并两个已排序的子序列以产生已排序的答案。

    当待排序列长度为1时,递归“开始回升”,这时不进行任何操作,因为长度为1已经排好序。

  • M e r g e S o r t ( A , p , q , r ) MergeSort(A,p,q,r) MergeSort(A,p,q,r)函数参数如下:

    A A A是一个数组, p 、 q 、 r p、q、r pqr是数组下标,满足 p ≤ q < r p\leq q<r pq<r

    该过程假设子数组 A [ p . . q ] A\left[p..q\right] A[p..q] A [ q + 1.. r ] A\left[q+1..r\right] A[q+1..r]都已经排好序,函数只需将两子数组依次遍历,按从小到大的顺序比对,再更新原本的数组即可。

  • 代码:时间复杂度 O ( n l o g ( n ) ) O\big(nlog(n)\big) O(nlog(n))

    #include <iostream>
    using namespace std;
    void Merge(int* A, int p, int q, int r) {
        int n1 = q - p + 1;
        int n2 = r - q;
        int* L = new int[n1 + 1];
        int* R = new int[n2 + 1];
        for (int i = 0; i < n1; ++i) {
            L[i] = A[p + i];
        }
        for (int j = 0; j < n2; ++j) {
            R[j] = A[q + j + 1];
        }
        L[n1] = INT_MAX;
        R[n2] = INT_MAX;
        int i = 0, j = 0;
        for (int k = p; k <= r; ++k) {//two subint ASC
            if (L[i] <= R[j]) {
                A[k] = L[i];
                i++;
            }
            else {
                A[k] = R[j];
                j++;
            }
        }
        return;
    }
    void MergeSort(int* A, int p, int r) {
        if (p < r) {
            int q = (p + r) / 2;
            MergeSort(A, p, q);
            MergeSort(A, q + 1, r);
            Merge(A, p, q, r);
        }
        return;
    }
    int main() {
        int A[8] = { 2,4,5,7,1,2,3,6 };
        MergeSort(A, 0, sizeof(A)/sizeof(int) -1);
        for (int i = 0; i < sizeof(A)/sizeof(int); ++i) {
            cout << A[i] << endl;
        }
        return 0;
    }
    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值