内部几类排序代码,无详细排序过程介绍,整理统计,参考网上资料及曾经学习的ppt,有错误望指正

/*email:1171839091@qq.com   如代码有问题请找我,我好改改,谢谢!*/

#include<iostream>
using namespace std;


template<typename T>
class sort      //排序类      注:可以把数组当作类的数据成员
{
public:
    sort() {}
    ~sort() {}

    void Swap(T *arr, int i, int j);      //交换两个数组元素

    void Insert_sort(T *arr, int n);      //直接插入排序---稳定算法---时间复杂度O(n*n)
    void Binary_insert_sort(T *arr, int n);      //折半插入排序---稳定算法---时间复杂度O(n*n)   用到了二分法查找元素
    void Modfiy_insert_sort(T *arr, int n, int delt, int m);      //与希尔排序关联 修改的插入排序算法,delta为增量,m表示为第m+1个子序列      
    void Shell_sort(T *arr, int n);      //希尔排序---不稳定算法---时间复杂度O(n的3/2次幂)
    
    void Bubble_sort(T *arr, int n);      //冒泡排序---稳定算法---时间复杂度O(n*n)
    void Quick_sort(T *arr, int low, int high);      //快速排序---不稳定算法---时间复杂度O(n*logn)
    int Partition(T *arr, int low, int high);      //与快速排序关联  分割算法-确定轴值位置
    int Partition2(T *arr, int low, int high);      //与快速排序关联  分割算法-确定轴值位置

    void Select_sort(T *arr, int n);      //直接选择排序---不稳定算法---时间复杂度(O(n*n)
    //void Heap_sort(T *arr, int n);      //堆排序---不稳定算法---时间复杂度O(n*logn)   放于堆中

    void Megre_sort(T *arr, T *temp, int left, int right);      //递归排序---稳定算法---时间复杂度O(n*logn)
    void Megre(T *arr, T *temp, int left, int middle, int right);      //合并两个有序数组

    /*最大值为三位数:1. 按照个位数进行排序。2. 按照十位数进行排序。3. 按照百位数进行排序。排序后,数列就变成了一个有序序列。*/
    //参考资料 countsort中的int 【n】,用new建动态数组
    //https://www.cnblogs.com/skywang12345/p/3603669.html 
    T Get_max(T *arr, int n);      //获取数组中的最大值
    void Count_sort(T *arr, int n, int exp);      //计数排序
    void Radix_sort(T *arr, int n);      //基数排序
};

template<typename T> T sort<T>::Get_max(T *arr, int n)     //获取数组中的最大值
{
    int max = arr[0];
    for (int i = 1; i < n; i++)
    {
        if (arr[i] > max)
        {
            max = arr[i];
        }
    }
    return max;
}

template<typename T> void sort<T>::Count_sort(T *arr, int n, int exp)      //计数排序
{
    T *temp;
    temp = new T[n];      // 存储"被排序数据"的临时数组
    int i;
    int buckets[10] = { 0 };      // 将数据出现的次数存储在buckets(桶)[]中  
    for (i = 0; i < n; i++)
    {
        buckets[(arr[i] / exp) % 10]++;
    }
    for (i = 1; i < 10; i++)      // 更改buckets[i]。目的是让更改后的buckets[i]的值,是该数据在temp[]中的位置。
    {
        buckets[i] += buckets[i - 1];
    }
    for (i = n - 1; i >= 0; i--)      // 将数据存储到临时数组temp[]中
    {
        temp[buckets[(arr[i] / exp) % 10] - 1] = arr[i];
        buckets[(arr[i] / exp) % 10]--;
    }
    for (i = 0; i < n; i++)      // 将排序好的数据赋值给arr[]
    {
        arr[i] = temp[i];
    }
    delete[] temp;
    for (i = 0; i < n; i++)     //测试每趟arr数组调用Count_sort后arr[]的顺序
    {
        cout << arr[i] << " ";
    }
    cout << endl;
}

template<typename T> void sort<T>::Radix_sort(T *arr, int n)      //基数排序
{
    int exp;
    int max = Get_max(arr, n);
    //cout << max << endl;
    for (exp = 1; max / exp > 0; exp *= 10)      //exp第一次为1,后每次*10,然后进行max/exp判断
    {
        Count_sort(arr, n, exp);      //调用计数排序
    }
}

template<typename T> void sort<T>::Megre(T *arr, T *temp, int left, int middle, int right)      //合并两个有序数组
{
    int i = left;
    int j = middle + 1;
    int t = 0;
    while (i <= middle && j <= right)      //找出两个区间的较小的值,然后赋给temp数组
    {
        if (arr[i] <= arr[j])
        {
            temp[t++] = arr[i++];
        }
        else
        {
            temp[t++] = arr[j++];
        }
    }
    while (i <= middle)      //右区间已结束,把左区间剩下的一齐赋给temp(临时)数组
    {
        temp[t++] = arr[i++];
    }
    while (j <= right)      //左区间已结束,把右区间剩下的一齐赋给temp(临时)数组
    {
        temp[t++] = arr[j++];
    }
    t = 0;
    for (int m = left; m <= right; m++)      //把temp数组整体赋值给arr(目标)数组,这样就完成两个有序序列的合并
    {
        arr[m] = temp[t++];
    }
}

template<typename T> void sort<T>::Megre_sort(T *arr, T *temp, int left, int right)      //递归排序---稳定算法---时间复杂度O(n*logn)
{
    int middle;
    if (left < right)
    {
        middle = (left + right) / 2;      //从中间划为两个子序列
        Megre_sort(arr, temp, left, middle);      //对左区间进行递归
        Megre_sort(arr, temp, middle + 1, right);      //对右区间进行递归
        Megre(arr, temp, left, middle, right);      //合并两个有序数组
    }
}

template<typename T> void sort<T>::Select_sort(T *arr, int n)      //直接选择排序---不稳定算法---时间复杂度(O(n*n)
{
    int smallest;      //最小元素下标
    for (int i = 0; i < n; i++)
    {
        smallest = i;      //排序开始前,以当前还未完成排序的序列的第一个元素为最小值
        for (int j = i; j < n; j++)
        {
            if (arr[j] < arr[smallest])      //比较发现是否有更小的记录,若有,则记录它的位置
            {
                smallest = j;
            }
        }
        Swap(arr, i, smallest);      //将第i+1个最小的记录放在数组中第i+1个位置

    }
}

template<typename T> int sort<T>::Partition(T *arr, int first, int last)      //与快速排序关联  分割算法-确定轴值位置
{
    int low = first + 1;      //初始值就是序列的第二个元素
    int high = last;      //最后一个元素的下标
    T pivot = arr[first];      //备份轴值---为第一个元素
    while (low <= high)
    {
        while (arr[low] < pivot && low <= high)      //从high所指的位置向左搜索,找到第一个小于轴的元素
        {
            low++;
        }
        while (arr[high] > pivot && low <= high)      //从low开始向右,找到第一个大于轴的元素
        {
            high--;
        }
        if (low < high)
        {
            Swap(arr, low, high);      //交换找到的两个元素
            low++;
            high--;
        }
        else
        {
            low++;
        }
    }
    Swap(arr, first, high);      //把轴放在high所指的位置
    return high;
}

template<typename T> int sort<T>::Partition2(T *arr, int low, int high)      //与快速排序关联  分割算法-确定轴值位置
{
    T pivot = arr[low];      //备份轴值---为第一个元素
    while (low < high)
    {
        while (low < high && arr[high] >= pivot)      //从high向左找到第一个小于轴的元素
        {
            high--;
        }
        Swap(arr, low, high);      //放在low的位置
        while (low<high && arr[low] <= pivot)      //从low向右找到第一个大于轴的元素
        {
            low++;
        }
        Swap(arr, high, low);      //放在high的位置
    }
    arr[low] = pivot;      //把轴放在low所指的位置
    return low;
}

template<typename T> void sort<T>::Quick_sort(T *arr, int low, int high)      //快速排序---不稳定算法---时间复杂度O(n*logn)
{
    int pivot;      //轴值位置下标定义
    if (low < high)
    {
        //pivot = Partition(arr, low, high);
        pivot = Partition2(arr, low, high);      //确定轴值位置下标
        Quick_sort(arr, low, pivot - 1);
        Quick_sort(arr, pivot + 1, high);
    }
}

template<typename T> void sort<T>::Bubble_sort(T *arr, int n)      //冒泡排序---稳定算法---时间复杂度O(n*n)
{
    int i, j;
    bool flag;
    for (i = 0; i < n; i++)
    {
        flag = true;      //标记位,用来判断后面的序列是否已经有序
        for (j = n - 1; j > i; j--)
        {
            if (arr[j] < arr[j - 1])
            {
                Swap(arr, j, j - 1);
                flag = false;      //发生了交换,未排序的序列不是有序
            }
        }
        if(flag)      //未排序的部分序列已经有序,不用做冒泡排序
        { 
            return;
        }
    }
}

template<typename T> void sort<T>::Swap(T *arr, int i, int j)      //交换两个数组元素
{
    T temp;
    temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

template<typename T> void sort<T>::Insert_sort(T *arr, int n)      //直接插入排序---稳定算法---时间复杂度O(n*n)
{
    int i, j;
    int temp;
    for (i = 1; i < n; i++)
    {
        temp = arr[i];      //第i+1个数组元素进行插入排序
        for (j = i - 1; j >= 0; j--)
        {
            if (arr[j] > temp)      //将大于第i+1个数组元素的数组元素后移
            {
                Swap(arr, j, j + 1);
            }
            else
            {
                break;      //已找到正确位置,位置下标为i+1,跳出查找循环
            }
        }
        arr[j + 1] = temp;      //将第i+1(下标为i)个数组元素插入正确位置
    }
}

template<typename T> void sort<T>::Modfiy_insert_sort(T *arr, int n, int delt, int m)      //修改的插入排序算法,delta为增量,m表示为第m+1个子序列      
{
    int i, j;
    for (i = m + delt; i < n; i += delt)      //子序列第一个元素为arr[m],从第二个元素arr[i+delt]开始插入排序
    {
        for (j = i; j >= delt; j -= delt)
        {
            if (arr[j ] < arr[j - delt])
            {
                Swap(arr, j, j - delt);      //直接交换相邻的两个无序的数组元素的值
            }
            else
            {
                break;
            }
        }
    }
}

template<typename T> void sort<T>::Shell_sort(T *arr, int n)      //希尔排序---不稳定算法---时间复杂度O(n的3/2次幂)
{
    int delt;
    for (delt = n / 2; delt > 0; delt /= 2)      //缩小增量delt排序,delt每次除以2递减      
    {
        for (int i = 0; i < delt; i++)      //共有delt个序列      
        {
            Modfiy_insert_sort(arr, n, delt, i);      //对i+1个子序列用插入排序
        }
    }
    Modfiy_insert_sort(arr, n, 1, 0);      //如果增量序列不能确保最后一个delt间距为1,则用这个扫尾性质的插入排序
}

template<typename T> void sort<T>::Binary_insert_sort(T *arr, int n)      //折半插入排序---稳定算法---时间复杂度O(n*n)
{
    int middle;
    T temp;
    for (int i = 1; i < n; i++)
    {
        int right = i - 1;      
        int left = 0;
        temp = arr[i];
        while (left <= right)
        {
            middle = (left + right) / 2;      //取中间点
            if (temp >= arr[middle])
            {
                left = middle + 1;      //取右区间
            }
            else
            {
                right = middle - 1;      //取左区间
            }
        }
        for (int j = i - 1; j >= left; j--)
        {
            Swap(arr, j, j + 1);      //元素后移,空出插入位,位置下标为left
        }
        arr[left] = temp;
    }
}

int main()
{
    int data;

    int i;
    sort<int> sort;
    //int arr[10] = { 88,55,33,77,11,99,22,00,44,66 };
    int arr[20] = { 23,43,5,45,36,7,66,54,32,89,11,99,45,34,76,23,87,45,23,1 };
    //int temp[20];      //归并排序的临时数组
    cout << "遍历未排序的数组:";
    for (i = 0; i < 20; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;

    //sort.Heap_sort(arr, 20);      //放于最大堆文件中了
    //sort.Megre_sort(arr, temp, 0, 19);
    //sort.Select_sort(arr, 20);
    //sort.Quick_sort(arr, 0, 19);
    //sort.Bubble_sort(arr, 10);
    //sort.Shell_sort(arr, 10);
    //sort.Insert_sort(arr, 10);
    //sort.Binary_insert_sort(arr, 10);
    sort.Radix_sort(arr, 20);
    cout << "遍历排序后的数组:";
    for (i = 0; i < 20; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;

    cin >> data;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值