进击的暑假(五)--常见的排序算法

目录

冒泡排序

简单选择排序

三层for循环的插入排序(最原始插入排序)

插入排序

带哨兵的插入排序

折半插入排序

插入排序的优化版本--希尔排序

希尔排序(自己规定增量序列)

归并排序

二路归并排序(参考别人的)

严蔚敏版二路归并实现

快速排序(挖坑法)

堆排序实现

基数排序

借助list,实现基数排序


 

冒泡排序

冒泡排序常规版本:

#include <iostream>
using namespace std;
void ipanel_bubble_sort(int *arr, int sz)
{
    for(int j = (sz -1) ;j>0;j--)//j的边界到1就好,可以完成排序
    {
        for(int i = 0;i < j; i++)
        {
            if(arr[i] > arr[i+1])
            {
                int tmp;
                tmp = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = tmp;
            }
        }
    }
}
int main()
{
    int arr[] = {7, 1, 3, 4, 8, 5};
    int index = 0;
    int size = sizeof(arr)/ sizeof(int);
    ipanel_bubble_sort(arr, size);
    for(;index< size;index++)
        cout << arr[index] << " " ;
}

冒泡排序常规版本不用临时变量(tmp)

#include <iostream>
using namespace std;
void bubble_sort(int *arr, int sz)
{
    for(int j = (sz -1) ;j>0;j--)
    {
        for(int i = 0;i < j; i++)
        {
            if(arr[i] > arr[i+1])
            {
                arr[i] += arr[i+1];
                arr[i+1] = arr[i] - arr[i+1];
                arr[i] -= arr[i+1];
            }
        }
    }
}
int main()
{
    int arr[] = {7, 1, 3, 4, 8, 5};
    int index = 0;
    int size = sizeof(arr)/ sizeof(int);
    bubble_sort(arr, size);
    for(;index< size;index++)
        cout << arr[index] << " ";
}

冒泡排序改进版本(加入exchange变量)

加入exchange标志变量,如果内部循环的时候,已经没有要交换顺序的操作,说明数组已经排好顺序,可以终止趟数。

#include <iostream>
using namespace std;
void ipanel_bubble_sort(int *arr, int sz)
{
    for(int j = (sz -1) ;j>0;j--)
    {
        bool exchange = false;
        for(int i = 0;i < j; i++)
        {
            if(arr[i] > arr[i+1])
            {
                int tmp = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = tmp;
                if(!exchange){exchange = true;}
            }
        }
        if(!exchange) break;
    }
}

int main()
{
    int arr[] = {7,1,2,3,4,5,6};
    int index = 0;
    int size = sizeof(arr)/ sizeof(int);
    ipanel_bubble_sort(arr, size);
    for(;index< size;index++)
        cout << arr[index] << " " ;
}

简单选择排序

#include <iostream>
using namespace std;
void swap(int &x, int &y)
{
    int tmp = x;
    x = y;
    y = tmp;
}
void sel_sort(int *arr, int sz)//sz个数
{
    for(int i = 0; i < (sz - 1); ++i)//sz-1趟
    {
        int k = i;
        for(int j = i + 1; j <= (sz - 1); ++j)//找arr中最小数和arr[0]交换位置,后面以此类推
        {
            if(arr[j] < arr[k]) k = j;
        }
        if(k != i)//下标不相等才交换位置,否则不交换
        {
            swap(arr[i], arr[k]);
        }
    }
}
int main()
{
    int arr[] = {7,10,2,30,14,5,0};
    int size = sizeof(arr)/ sizeof(int);
    sel_sort(arr, size);
    for(int index = 0;index< size;index++)
        cout << arr[index] << " " ;
}

三层for循环的插入排序(最原始插入排序)

#include <iostream>
using namespace std;
void in_sort(int *arr, int n)
{
    for (int i = 1; i < n; ++i) {
        if(arr[i] < arr[i-1]){
            int tmp = arr[i];
            for (int j = 0; j < i; ++j) {
                if(tmp < arr[j]){
                    for (int k = i; k > j; --k) {
                        arr[k] = arr[k-1];
                    }
                    arr[j] = tmp;
                    break;
                }
            }
        }
    }
}

int main()
{
    int arr[] = {11,22,0,9,8,100,33};
    int size = sizeof(arr) / sizeof(int);
    in_sort(arr, size);
    for (int i = 0; i <size ; ++i) {
        cout<< arr[i]<<" ";
    }
    cout<<endl;
}

插入排序

#include <iostream>
using namespace std;
//排序一和排序二逻辑上没有什么不同,只是while循环的写法不一样
void ins_sort_1(int *arr, int sz)
{
    int tmp, j ;
    for(int i = 1; i <= (sz-1); ++i ){
        if (arr[i] < arr[i - 1]) {
            tmp = arr[i];
            j = i - 1;
            do {
                arr[j + 1] = arr[j];
                --j;
            }while (j >= 0 && tmp < arr[j]);
            arr[j + 1] = tmp;
        }
    }
}
void ins_sort_2(int *arr, int sz)
{
    for(int i = 1;i<sz;++i){//一趟完成之后前i+1个就是有序的
        int key = arr[i];
        int j = i -1;
        while ((j>=0) && (key < arr[j])){
            arr[j +1] =arr[j];
            j--;
        }
        arr[j+1] = key;
    }
}
int main()
{
    int arr[] = {47, 15, 40, 28, 10, 2, 14, 25, 32, 29};
    int size = sizeof(arr)/ sizeof(int);
    //ins_sort_1(arr, size);
    ins_sort_2(arr, size);
    for(int index = 0;index< size;index++)
        cout << arr[index] << " " ;
}

带哨兵的插入排序

#include <iostream>
using namespace std;
void in_sort_2(int *arr, int n)
{
    for (int i = 2; i < n; ++i) {
        int j;
        if(arr[i] < arr[i-1]){
            arr[0] = arr[i];
            //arr[i] = arr[i-1];
            for (j = i; arr[0] < arr[j-1]; --j) {
                arr[j] = arr[j-1];
            }
            arr[j] = arr[0];
        }
    }

}
int main()
{
    int arr[] = {0,11,22,0,90000,8,100,33};//arr[0]是哨兵,有两个作用:一方面是作为临时空间,另一方面是作为循环终止的条件。
    int size = sizeof(arr) / sizeof(int);
    in_sort_2(arr, size);
    for (int i = 1; i <size ; ++i) {
        cout<< arr[i]<<" ";
    }
    cout<<endl;
}

折半插入排序

#include <iostream>
using namespace std;
void half_ins_sort(int *arr, int n)
{
    for (int i = 2; i < n; ++i) {
        arr[0] = arr[i];
        int lo = 1,hi = i-1;
        while (lo <= hi ){
            int mid = (lo + hi) / 2;
            if(arr[0] < arr[mid])
                hi = mid-1;
            else
                lo = mid +1;
        }
        for (int j = i; j >lo ; --j) {
            arr[j] = arr[j-1];
        }
        arr[lo] =arr[0];
    }
}
int main()
{
    int arr[] = {0,11,22,0,90000,8,100,33};//arr[0]作为临时空间
    int size = sizeof(arr) / sizeof(int);
    half_ins_sort(arr, size);
    for (int i = 1; i <size ; ++i) {
        cout<< arr[i]<<" ";
    }
    cout<<endl;
}

插入排序的优化版本--希尔排序

#include <iostream>
using namespace std;
void shell_sort(int arr[],int len)
{
    int gap, i, j;
    int tmp;
    for(gap = len >> 1;gap > 0;gap >>= 1){
        for (int i = gap; i <len ; ++i) {
            tmp = arr[i];
            for (j = i-gap; j>=0 && arr[j] > tmp ; j -= gap) {
                arr[j+gap] = arr[j];
            }
            arr[j+gap] = tmp;
        }
    }
}

int main()
{
    int arr[] = {47, 15, 40, 28, 10, 2, 14};
    int size = sizeof(arr)/ sizeof(int);
    shell_sort(arr, size);
    for(int index = 0;index< size;index++)
        cout << arr[index] << " ";
    cout<<endl;
}

希尔排序的时间复杂度和其步长有关,步长有多种选取方式,本例的步长使用的是(n/2)。当希尔排序的步长最后为1的时候,

其实就是插入排序,此时待排的序列,已经基本有序了。

希尔排序(自己规定增量序列)

#include <iostream>
using namespace std;
void shell_ins_sort (int *arr, int n, int gap)
{
    int j;
    for (int i = gap; i < n; ++i) {
        if(arr[i] < arr[i-gap]){
            int tmp = arr[i];
            for(j = i-gap;j>=0&&tmp<arr[j];j -= gap){
                arr[j+gap] = arr[j];
            }
            arr[j+gap] = tmp;
        }
    }
}
void shell_sort(int *arr, int n, int *gaps, int t)
{
    for (int i = 0; i < t; ++i) {
        shell_ins_sort(arr, n , gaps[i]);
    }
}
int main()
{
    int gaps[] = {5,3,2,1};
    int arr[] = {11,22,0,90000,8,100,33};
    int size = sizeof(arr) / sizeof(int);
    shell_sort(arr,size,gaps,(sizeof(gaps) / sizeof(int)));
    for (int i = 0; i <size ; ++i) {
        cout<< arr[i]<<" ";
    }
    cout<<endl;
}

归并排序

#include <iostream>
using namespace std;
void merge_sort_recursive(int arr[], int reg[], int start, int end) {
    if (start >= end)
        return;
    int len = end - start, mid = (len >> 1) + start;
    int start1 = start, end1 = mid;
    int start2 = mid + 1, end2 = end;
    merge_sort_recursive(arr, reg, start1, end1);
    merge_sort_recursive(arr, reg, start2, end2);
    int k = start;
    while (start1 <= end1 && start2 <= end2)
        reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
    while (start1 <= end1)
        reg[k++] = arr[start1++];
    while (start2 <= end2)
        reg[k++] = arr[start2++];
    for (k = start; k <= end; k++)
        arr[k] = reg[k];
}

void merge_sort(int arr[], const int len) {
    int reg[len];
    merge_sort_recursive(arr, reg, 0, len - 1);
}

int main()
{
    int arr[] = {2,3,5,6,8,7,4};
    int size = sizeof(arr)/ sizeof(int);
    merge_sort(arr, size);
    for(int index = 0;index< size;index++)
        cout << arr[index] << " ";
    cout<<endl;
}

二路归并排序(参考别人的)

#include <iostream>
using namespace std;
void merge(int *a, int lo, int mi, int hi)
{
    int nl = mi - lo + 1;//左边的长度
    int nr = hi - mi;//右边的长度

    int *L = new int[nl + 1];//空出一个哨兵的位置
    int *R = new int[nr + 1];
    L[nl] = 100000;//左边队列的哨兵
    R[nr] = 100000;//右边队列的哨兵
    int i, j, k;
    for (i = 0; i < nl; i++) {
        L[i] = a[lo + i];//把左边部分的值赋给一个保存左边值的临时队列
    }

    for (j = 0; j < nr; j++)
        R[j] = a[mi + 1 + j];

    //k从lo的位置开始
    for (i = 0, j = 0, k = lo; k <= hi; k++) {
        if (L[i] <= R[j]) {//把较小的值赋给主队列(用了哨兵这里可以少写两个循环)
            a[k] = L[i];
            i++;
        }
        else {
            a[k] = R[j];
            j++;
        }
    }

    delete[]L;
    delete[]R;
}

void mergeSort(int *a, int lo, int hi)
{
    if (lo < hi) {
        int mi = (lo + hi) >> 1;
        mergeSort(a, lo, mi);
        mergeSort(a, mi + 1, hi);
        merge(a, lo, mi, hi);
    }
}

int main()
{
    int a[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};
    int n = sizeof(a) / sizeof(a[0]);
    int lo = 0;
    int hi = n - 1;
    mergeSort(a, lo, hi);
    for (int i = 0; i <n ; ++i) {
        cout<<a[i]<<" ";
    }
}

严蔚敏版二路归并实现

#include <iostream>
using namespace std;
void Merge(int *SR, int *TR, int i, int m, int n)
{
    int j = m+1;
    int k = i;
    for (;i<=m&&j<=n;++k){
        if(SR[i] <= SR[j]){
            TR[k] = SR[i++];
        }
        else{
            TR[k] = SR[j++];
        }
    }
    while (i<=m){
        TR[k++] = SR[i++];
    }
    while (j<=n){
        TR[k++] = SR[j++];
    }
}
void Msort(int *SR, int *TR1, int s ,int t)
{
    if(s == t){
        TR1[s] = SR[s];
    }
    else{
        int *TR2 = new int [100];
        int m = (s + t) / 2;
        Msort(SR, TR2, s, m);
        Msort(SR,TR2,m+1,t);
        Merge(TR2,TR1,s,m,t);
        delete[]TR2;
    }

}
int main()
{
    int arr[] = {11,22,0,90000,8,11,33, 44, 56, 78, 1,4,5,7,6};
    int size = sizeof(arr) / sizeof(int);
    Msort(arr, arr, 0, size-1);//传两个一模一样的参数还是有点迷,真的是
    for (int i =0; i <size ; ++i) {
        cout<< arr[i]<<" ";
    }
    cout<<endl;
}

快速排序(挖坑法)

#include <iostream>
using namespace std;
int partion(int arr[], int lo, int hi)
{
    int privot = arr[lo];
    while (lo < hi)
    {
        while ((lo<hi)&&(privot <= arr[hi]))
            hi--;
        arr[lo] = arr[hi];
        while ((lo< hi)&&(arr[lo])<= privot)
            lo++;
        arr[hi] = arr[lo];
    }

    arr[lo] = privot;//用privot填坑
    return lo;

}
void QuickSort(int arr[], int lo, int hi)//QuickSort函数[ )
{
    if (hi - lo < 2) return;//单元素区间,自然有序
    int mid = partion(arr, lo, hi-1);
    QuickSort(arr, lo, mid );
    QuickSort(arr, mid + 1, hi);
}
int main()
{
     int arr[] = {};
     int size = sizeof(arr) / sizeof(int);
     QuickSort(arr, 0, size);
    for (int i = 0; i <size ; ++i) {
        cout<<arr[i]<<" ";
    }

}

堆排序实现

#include <stdio.h>
#include <stdlib.h>
void swap(int *a, int *b) {
    int temp = *b;
    *b = *a;
    *a = temp;
}

void max_heapify(int arr[], int start, int end) {
    // 建立父節點指標和子節點指標
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end) { // 若子節點指標在範圍內才做比較
        if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的
            son++;
        if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數
            return;
        else { // 否則交換父子內容再繼續子節點和孫節點比较
            swap(&arr[dad], &arr[son]);
            dad = son;
            son = dad * 2 + 1;
        }
    }
}

void heap_sort(int arr[], int len) {
    int i;
    // 初始化,i從最後一個父節點開始調整
    for (i = len / 2 - 1; i >= 0; i--)
        max_heapify(arr, i, len - 1);
    // 先將第一個元素和已排好元素前一位做交換,再重新調整,直到排序完畢
    for (i = len - 1; i > 0; i--) {
        swap(&arr[0], &arr[i]);
        max_heapify(arr, 0, i - 1);
    }
}

int main() {
    int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
    int len = (int) sizeof(arr) / sizeof(*arr);
    heap_sort(arr, len);
    int i;
    for (i = 0; i < len; i++)
        printf("%d ", arr[i]);
    printf("\n");
    return 0;
}

基数排序

#include <iostream>
using namespace std;
int maxbit(int data[], int n) //辅助函数,求数据的最大位数
{
    int maxData = data[0];		///< 最大数
    /// 先求出最大数,再求其位数,这样有原先依次每个数判断其位数,稍微优化点。
    for (int i = 1; i < n; ++i)
    {
        if (maxData < data[i])
            maxData = data[i];
    }
    int d = 1;
    int p = 10;
    while (maxData >= p)
    {
        //p *= 10; // Maybe overflow
        maxData /= 10;
        ++d;
    }
    return d;
/*    int d = 1; //保存最大的位数
    int p = 10;
    for(int i = 0; i < n; ++i)
    {
        while(data[i] >= p)
        {
            p *= 10;
            ++d;
        }
    }
    return d;*/
}
void radixsort(int data[], int n) //基数排序
{
    int d = maxbit(data, n);
    int *tmp = new int[n];
    int *count = new int[10]; //计数器
    int i, j, k;
    int radix = 1;
    for(i = 1; i <= d; i++) //进行d次排序
    {
        for(j = 0; j < 10; j++)
            count[j] = 0; //每次分配前清空计数器
        for(j = 0; j < n; j++)
        {
            k = (data[j] / radix) % 10; //统计每个桶中的记录数
            count[k]++;
        }
        for(j = 1; j < 10; j++)
            count[j] = count[j - 1] + count[j]; //将tmp中的位置依次分配给每个桶
        for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中
        {
            k = (data[j] / radix) % 10;
            tmp[count[k] - 1] = data[j];
            count[k]--;
        }
        for(j = 0; j < n; j++) //将临时数组的内容复制到data中
            data[j] = tmp[j];
        radix = radix * 10;
    }
    delete []tmp;
    delete []count;
}

int main()
{
    int arr[] = {999, 33, 2, 52 ,90};
    int size = sizeof(arr) / sizeof(int);
    radixsort(arr, size);
    for (int i = 0; i < size; ++i) {
        cout<< arr[i]<< " ";
    }
}

借助list,实现基数排序

#include <iostream>
#include <list>
using namespace std;
list<int> lt[10];
int maxbit(int data[], int n) //辅助函数,求数据的最大位数
{
    int maxData = data[0];        ///< 最大数
    /// 先求出最大数,再求其位数,这样有原先依次每个数判断其位数,稍微优化点。
    for (int i = 1; i < n; ++i) {
        if (maxData < data[i])
            maxData = data[i];
    }
    int d = 1;
    int p = 10;
    while (maxData >= p) {
        //p *= 10; // Maybe overflow
        maxData /= 10;
        ++d;
    }
    return d;
}
int Getkey(int value, int k)
{
    int key;
    while(k>0)
    {
        key = value % 10;
        value /= 10;
        k--;
    }
    return key;
}
void Distrubute(int *ar, int n, int k)
{
    for(int i=0; i<n; ++i)
    {
        int key = Getkey(ar[i], k);
        lt[key].push_back(ar[i]);
    }
}
void Collect(int *ar)
{
    int n = 0;
    list<int>::iterator it;
    for(int i=0; i<10; ++i)
    {
        it = lt[i].begin();
        while(it != lt[i].end())
        {
            ar[n++] = *it;
            ++it;
        }
        lt[i].clear();
    }
}

void RadixSort(int *ar, int n)
{
    int k = maxbit(ar,n);
    for(int i=1; i<=k; ++i)
    {
        Distrubute(ar, n, i);
        Collect(ar);
    }

}
int main()
{
    int arr[] = {11,22,0,8,11,33, 44, 56, 78, 1,4,5,7,6,10000,55555};
    int size = sizeof(arr) / sizeof(int);
    RadixSort(arr,size);
    for (int i =0; i <size ; ++i) {
        cout<< arr[i]<<" ";
    }
    cout<<endl;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值