经典算法——八大排序算法总结

本文深入讲解了多种排序算法的特点及实现方式,包括插入排序、冒泡排序、选择排序、归并排序、快速排序等,并提供了详细的伪代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

比较各种排序算法的时间空间消耗

这里写图片描述
这里写图片描述

下面分别给出各算法的特性及伪代码

  1. 插入排序
    特点:stable sort、In-place sort,最好O(N),最坏O(N^2)
    这里写图片描述

  2. 冒泡排序
    特点:stable sort、In-place sort
    思想:通过两两交换,像水中的泡泡一样,小的先冒出来,大的后冒出来。
    这里写图片描述
    这里写图片描述

  3. 选择排序
    特性:In-place sort,unstable sort。
    思想:每次找一个最小值。最好情况时间:O(n^2),最坏情况时间:O(n^2)。
    这里写图片描述
  4. 归并排序
    特点:stable sort、Out-place sort
    思想:运用分治法思想解决排序问题。最坏情况运行时间:O(nlgn),最佳运行时间:O(nlgn)
    这里写图片描述
  5. 快速排序
    这里写图片描述
    改进当所有元素相同时的效率的Partition实现:
    这里写图片描述

  6. 堆排序
    这里写图片描述

  7. 计数排序
    这里写图片描述
  8. 基数排序
    这里写图片描述

代码实现:

#include<iostream>
#include<vector>
#include<algorithm>
#include<ctime>
#include<cstdlib>
using namespace std;

// 插入排序
void insert_sort(vector<int>& v, int l, int r){
    if(l<r){
        for(int i=l+1; i<=r; i++){
            int j=i-1;
            int key = v[i];
            while(j>=l && v[j]>=key){
                v[j+1] = v[j];
                j--;
            }
            v[j+1] = key;
        }
    }
}


//  冒泡排序
void bubble_sort(vector<int>& v, int l, int r){
    if(l<r){
        bool flag = true;  //表示是否有交换
        for(int i=l; i<r; i++){
            if(flag == false) return;
            for(int j=r; j>i; j--){
                if(v[j]<v[j-1]){
                    swap(v[j],v[j-1]);
                    flag = true;
                }
            }
        }           
    }   
}

// 选择排序
void select_sort(vector<int>& v, int l, int r){
    if(l<r){
        for(int i=l; i<r; i++){
            int min = i;
            for(int j=i+1; j<=r; j++){
                if(v[j]<v[min]) min = j;
            }
            swap(v[min],v[i]);
        }
    }
}

// 归并排序
void merge(vector<int>& v, int l,int m, int r){
    if(l<r && m<r){
        int len1 = m-l+1;
        int len2 = r-m;

        int* a = new int[len1];
        int* b = new int[len2];

        for(int i=0; i<len1; i++) a[i] = v[l+i];
        for(int i=0; i<len2; i++) b[i] = v[m+1+i];

        int i,j;        
        int k=l;
        i=0,j=0;
        for( ;i<len1 && j<len2; ){
            if(a[i]<b[j]){
                v[k++] = a[i++];
            }
            else{
                v[k++] = b[j++];
            }
        }

        while(i<len1) v[k++] = a[i++];
        while(j<len2) v[k++] = b[j++];
        delete []a;
        delete []b;
    }
}

void merge_sort(vector<int>& v, int l, int r){
    if(l<r){
        int mid = (l+r)/2;
        merge_sort(v,l,mid);
        merge_sort(v,mid+1,r);
        merge(v,l,mid,r);
    }
}

// 快排
int partition(vector<int>& v, int l, int r){
    int pivot = v[r];
    int i=l-1;
    for(int j=l; j<r; j++){
        if(v[j]<pivot){
            i++;
            swap(v[i],v[j]);
        }
    }
    i++;
    swap(v[i],v[r]);
    return i;
}
void quick_sort(vector<int>& v, int l, int r){
    if(l<r){
        int m = partition(v,l,r);
        quick_sort(v,l,m-1);
        quick_sort(v,m+1,r);
    }   
}


// 堆排序
int parent(int i){
    return (i-1)/2;
}
int leftChild(int i){
    return 2*i+1;
}
int rightChild(int i){
    return 2*i+2;
}

void maxHeapify(vector<int>& v, int len, int i){
    int lchild = leftChild(i);
    int rchild = rightChild(i);
    int maxPos;
    if(lchild<len && v[lchild]>v[i]){
        maxPos = lchild;
    }
    else{
        maxPos = i;
    }
    if(rchild<len && v[rchild]>v[maxPos]){
        maxPos = rchild;
    }

    if(maxPos != i){
        swap(v[i],v[maxPos]);
        maxHeapify(v,len, maxPos);
    }
}

void buildHeap(vector<int>& v, int len){
    for(int i=parent(len-1); i>=0; i--){
        maxHeapify(v,len,i);
    }
}

void heap_sort(vector<int>& v, int len){
    buildHeap(v,len);
    for(int i=len-1; i>0; i--){
        swap(v[0],v[i]);
        --len;
        maxHeapify(v,len,0);
    }
}

// 计数排序
void count_sort(vector<int>& v, int len, int k){    

    vector<int> a(len);
    vector<int> b(k+1);
    for(int i=0; i<=k; i++) b[i] = 0;

    for(int i=0; i<len; i++) b[v[i]] += 1;

    for(int i=1; i<=k; i++) b[i] = b[i-1]+b[i];

    for(int i=len-1; i>=0; i--){
        a[b[v[i]]-1] = v[i];
        b[v[i]] -= 1;
    }

    for(int i=0; i<len; i++) v[i] = a[i];

}

// 基数排序
/*
 * Get the spcific digit of given number.
 * For example, number 234, 
 *  the 0st digit is 4, 
 *  the 1st digit is 3,
 *  the 2nd digit is 2,
 *  the 3th digit is 0.
 */
int GetNDigit(int nNumber, int nIdx)
{
    for (int i = nIdx; i > 0; i--) {
        nNumber /= 10;
    }
    return nNumber % 10;
}

/*
 * Counting Sort the given array according to specific digit.
 * array: 待排序数组.
 * nLength: 待排序数组长度
 * nIdxDigit: 排序要依据的位. 0为最低位,高位依次加1.
 * nK: *nIdxDigit位上可能出现的最大数字(对10进制数排序则nK=9).
 */
void CountingSort_SpecificDigit(vector<int>& array, size_t nLength, int nIdxDigit, int nK=9)
{
    if (0 == nLength || 0 == nK)
        return;

    int *digitNum = new int[nLength];
    memset(digitNum, 0, sizeof(int)*nLength);
    int *count = new int[nK+1];
    memset(count, 0, sizeof(int)*(nK+1));
    int *arrayResult = new int[nLength];
    memset(arrayResult, 0, sizeof(int)*nLength);

    // 数组digitNum[],保存每个元素指定位上的数字,作为排序依据
    for (int idx = 0; idx<nLength; idx++)
        digitNum[idx] = GetNDigit(array[idx], nIdxDigit);

    // 先计数,count[idx]为值等于idx的元素的个数
    for (int idx = 0; idx<nLength; idx++)
        count[digitNum[idx]]++;
    // 再累加,count[idx]为小于等于idx的元素的个数
    for (int idx = 1; idx<nK+1; idx++)
        count[idx] = count[idx] + count[idx-1];

    // 从后向前循环(保证排序稳定), 根据指定位的数字大小
    // 将array[idx]排在所有小于等于array[idx]的数(共count[digitNum[idx]]个)的后面
    for (int idx=nLength-1; idx>=0; idx--)
        {
        arrayResult[count[digitNum[idx]]-1] = array[idx];
        count[digitNum[idx]]--;
        }

    // 把排序结果写回原数组   
    for(int i=0; i<nLength; i++) array[i] = arrayResult[i];

    delete [] digitNum;
    delete [] count;
    delete [] arrayResult;
}
/*
 * 基数排序
 * array: 待排序数组
 * nLength: 待排序数组元素个数
 * nDigit: 所有元素的最大位数
 */
void radix_sort(vector<int>& array, size_t nLen, int nDigit)
{
    // 从最低位到最高位,依次调用计数排序
    for (int idx=0; idx<=nDigit; idx++) {
        CountingSort_SpecificDigit(array, nLen, idx);
    }
}
void printVec(vector<int>& v){
    int len = v.size();
    for(int i=0; i<len; i++){
        cout<<v[i]<<" ";        
    }   
}


int main(){
    srand(time(NULL));

    vector<int> v(10);

    for (int i = 0; i < 10; i++)
    {
        v[i] = rand()%100;
    }
    cout<<endl<<"排序前: ";
    printVec(v);

    insert_sort(v,0,v.size()-1);
    cout<<endl<<"插入排序后: ";
    printVec(v);


    for (int i = 0; i < 10; i++)
    {
        v[i] = rand()%100;
    }
    cout<<endl<<"排序前: ";
    printVec(v);

    bubble_sort(v,0,v.size()-1);
    cout<<endl<<"冒泡排序后: ";
    printVec(v);


    for (int i = 0; i < 10; i++)
    {
        v[i] = rand()%100;
    }
    cout<<endl<<"排序前: ";
    printVec(v);

    select_sort(v,0,v.size()-1);
    cout<<endl<<"选择排序后: ";
    printVec(v);


    for (int i = 0; i < 10; i++)
    {
        v[i] = rand()%100;
    }
    cout<<endl<<"排序前: ";
    printVec(v);

    merge_sort(v,0,v.size()-1);
    cout<<endl<<"归并排序后: ";
    printVec(v);

    for (int i = 0; i < 10; i++)
    {
        v[i] = rand()%100;
    }
    cout<<endl<<"排序前: ";
    printVec(v);

    quick_sort(v,0,v.size()-1);
    cout<<endl<<"快速排序后: ";
    printVec(v);

    for (int i = 0; i < 10; i++)
    {
        v[i] = rand()%100;
    }
    cout<<endl<<"排序前: ";
    printVec(v);

    heap_sort(v,10);
    cout<<endl<<"堆排序后: ";
    printVec(v);

    for (int i = 0; i < 10; i++)
    {
        v[i] = rand()%6;
    }
    cout<<endl<<"排序前: ";
    printVec(v);

    count_sort(v,10,5);
    cout<<endl<<"计数排序后: ";
    printVec(v);

    v.resize(20);
    for (int i = 0; i < 10; i++)
    {
        v[i] = rand()%100;
    }
    cout<<endl<<"排序前: ";
    printVec(v);

    radix_sort(v,20,1);
    cout<<endl<<"基数排序后: ";
    printVec(v);
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值