/*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;
}