头文件:
#include <iostream>
//1插入类的排序:
//希尔排序:取增量d1的分为一组,共分成d1组分别进行插入排序,然后每组对应元素放在一起,然后取d2...知道d=1
//希尔排序的代码可以近乎看成把1换成dk
/*我们简单处理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n为要排序数的个数
即:先将要排序的一组记录按某个增量d(n/2,n为要排序数的个数)分成若干组子序列,每组中记录的下标相差d.对每组中全部
元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。继续不断缩小增量直至
为1,最后使用直接插入排序完成排序。*/
//时间复杂度 O(n^3/2) 不稳定
void ShellSort(int a[], int n){
int i, j, dk;
for(dk = n/2; dk > 0; dk /= 2){
for(i = dk; i <= n; i++){
if(a[i] < a[i-dk]){
a[0] = a[i];
for(j = i-dk; a[j]>a[0] && j>=0; j -= dk)
a[j+dk] = a[j];
a[j+dk] = a[0];
}
}
}
}
//直接插入排序:将第一个数据看成有序表,将后面的数据一次插入表中
//时间复杂度 O(n^2) 稳定
void InsertSort(int a[], int n){
int i, j;
for(i = 1; i <= n; i++){
if(a[i] < a[i-1]){ //若插入的第i个数大于它的前一个数i-1,就直接插入再最后,如果小于,就移动有序表插入
a[0] = a[i]; //设置为哨兵,作用是用于暂时存放要插入的数
for(j = i-1; a[j]>a[0] && j>=0; j--)//从要插入数i的前一个数i-1开始,若比i大,就后移一位
a[j+1] = a[j];
a[j+1] = a[0]; //找到真确位置,将要插入数放在第j个数后面
}
}
}
//2归并类排序:
/*归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,
即把待排序序列分为若干个子序列,每个子序列是有序的。
然后再把有序子序列合并为整体有序序列。*/
//时间复杂度 O(nlogn) 稳定
//合并两个已经排好顺序的数组
void Merge(int a[], int start, int mid, int end, int *temp){
int i = start, j = mid+1, k = 0;//start到mid位数组1,mid+1到end为数组2
while(i<=mid && j<=end) //从两个数组最低位开始比较,数值小的存入临时数组
temp[k++] = (a[i] <= a[j]) ? a[i++] : a[j++];
while(i <= mid) //总有一个数组先比较完,所以处理剩下数组的元素
temp[k++] = a[i++];
while(j <= end)
temp[k++] = a[j++];
k = 0; //下面将排完序的临时数组里的数拷贝到原数组里
for(i = start; i <= end; i++)
a[i] = temp[k++];
}
//用分治法进行二路归并
void MergeSort(int a[], int start, int end, int *temp){
if(start < end){ //当数组至少有两个元素时,进行二路归并
int mid = (start+end)/2;
MergeSort(a, start, mid, temp);
MergeSort(a, mid+1, end, temp);
Merge(a, start, mid, end, temp);
}
}
//3交换类排序:
//快速排序
//时间复杂度 O(nlogn) 不稳定
void QuickSort(int a[], int n){
int low, high, p, t;
if(n < 2)//只有一个数,不用交换
return;
p = a[n/2]; //p取数组a的中间的数
for(low = 0, high = n-1;; low++, high--){ //从p的两边开始排序
while(p > a[low]) //将小于p的数放在左边,大于p的数放在p的右边
low++;
while(p < a[high])
high--;
if(low >= high) break;
t = a[low]; //如果p左边的数比p右边的那个数大,把p左右两边数交换一下
a[low] = a[high];
a[high] = t;
}
QuickSort(a, low); //第一个递归调用处理数组的前部分,a对应的是数组的首地址,low是指对应的元素个数
QuickSort(a+low, n-low);//第二个递归调用处理数组后部分,a + low指的当然是首地址加偏移地址,n-low就是p后面剩下的元素个数
}
//冒泡排序
//时间复杂度 O(n^2) 稳定
void BubbleSort(int a[], int n){
for(int i = 1; i <= n; i++) //每一趟结束都把一个最大的数放到最下面
for(int j = 1; j <= n-i; j++)
if(a[j] > a[j+1]){
int t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
//4选择类排序:
/*堆排序:初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),
调整它们的存储序,使之成为一个堆,将堆顶元素输出,
得到n 个元素中最大(或最小)的元素,这时堆的根节点的数最大(或者最小)。
然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次小(或次大)的元素。
依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列*/
//堆排序:树形选择排序,将带排序记录看成完整的二叉树,第一步:建立初堆,第二步:调整堆
//时间复杂度 O(nlogn) 不稳定
//第二步:调整堆
void HeapAdjust(int a[], int s, int n){ //调整为大根堆,从大到小
int rc = a[s];//rc根节点,s第一个节点,n节点数
for(int j = 2*s; j <= n; j *= 2){
if(j<n && a[j]<a[j+1])//判断左右子数大小
j++;
if(rc >= a[j])//直到找到比第一个节点大的数
break;
a[s] = a[j];
s = j;
}
a[s] = rc;
}
//第一步:建初堆
void CreatHeap(int a[], int n){ //大根堆
for(int i = n/2; i > 0; i--)
HeapAdjust(a, i, n);
}
//整合
void HeapSort(int a[], int n){
CreatHeap(a, n);//第一步建堆
for(int i = n; i > 1; i--){ //堆顶与最后一个元素互换
int x = a[1];
a[1] = a[i];
a[i] = x;
HeapAdjust(a, 1, i-1);
}
}
//简单选择排序:遍历一次找到最小与第一个元素互换位置,再从第二个元素开始遍历找到最小与第二个元素互换位置...
//时间复杂度 O(n^2) 稳定
void SelectSort(int a[], int n){
for(int i = 1; i < n; i++){ //第一趟共比较n-1次
int k = i; //k总是指向最小的那个数的下标,开始认为第一个数最小,然后把最小的数往上放
for(int j = i+1; j <= n; j++) //从个第二个数开始循环找出这组数中最小数的下标,并把它赋值给k
if(a[j] < a[k])
k = j;
if(k != i){ //若果最小的那个数不是开始排序的第一个数,那么就把最小的那个数和开始排序的第一个数交换
int t = a[i];
a[i] = a[k];
a[k] = t;
}
}
}
主函数:
#include <iostream>
#include<iomanip>
#include "Sort.h"
#define Max 101
using namespace std;
int main(){
cout << endl << endl << endl;
cout <<setw(45) << "******************";
cout << "综" <<setw(10) << "合"<< setw(10) << "排" << setw(10) << "序";
cout << "****************";
cout << endl << endl << endl;
cout <<setw(55) << "****************************";
cout << "菜" << setw(10) <<"单";
cout << "**************************";
cout << endl << endl;
cout <<" " << setw(93) << "--------------------------------------------------------------------";
cout << endl;
cout << " " << setw(40) << "+ 归并排序----0" << setw(53) << "+" << endl;
cout << " " << setw(26) << "+" << setw(67) << "+" << endl;;
cout <<" " << setw(40) << "+ 希尔排序----1" << setw(50) << "直接插入排序----2" << setw(3) << "+" << endl;
cout << " " << setw(26) << "+" << setw(67) << "+" << endl;
cout <<" " << setw(40) << "+ 快速排序----3" << setw(46) << "冒泡排序----4" << setw(7) << "+" << endl;
cout << " " << setw(26) << "+" << setw(67) << "+" << endl;
cout <<" " << setw(38) << "+ 堆排序----5" << setw(52) << "简单选择排序----6" << setw(3) << "+" << endl;
cout << " " << setw(26) << "+" << setw(67) << "+" << endl;
cout <<" " << setw(93) << "--------------------------------------------------------------------";
cout << endl << endl;
cout <<setw(55) << "*****************************";
cout << "退出程序----7";
cout << "**************************" << endl << endl;
cout << "(注意:选择排序算法时输入对应的编号即可)" << endl;
cout << endl;
int num, a[Max];
while(scanf("%d", &num) != EOF){
for(int i = 1; i <= Max-1; i++){
a[i] = rand();
}
if(num == 0){
cout << "您选择了归并排序:" << endl << endl;
int temp[Max-1] = {-1}; //临时数组,作为参数传递,避免每次在merge中分配临时数组
MergeSort(a, 1, Max-1, temp);
cout << "排序后:" << endl;
for(int i = 1; i <= Max-1; i++)
cout << left << setw(6) << a[i];
cout << endl << endl;
}
if(num == 1){
cout << "您选择了希尔排序:" << endl << endl;
ShellSort(a, Max-1);
cout << "排序后:" << endl;
for(int i = 1; i <= Max-1; i++)
cout << left << setw(6) << a[i];
cout << endl << endl;
}
if(num == 2){
cout << "您选择了直接插入排序:" << endl << endl;
InsertSort(a, Max-1);
cout << "排序后:" << endl;
for(int i = 1; i <= Max-1; i++)
cout << left << setw(6) << a[i];
cout << endl << endl;
}
if(num == 3){
cout << "您选择了快速排序:" << endl << endl;
QuickSort(a, Max-1);
cout << "排序后:" << endl;
for(int i = 1; i <= Max-1; i++)
cout << left << setw(6) << a[i];
cout << endl << endl;
}
if(num == 4){
cout << "您选择了冒泡排序:" << endl << endl;
BubbleSort(a, Max-1);
cout << "排序后:" << endl;
for(int i = 1; i <= Max-1; i++)
cout << left << setw(6) << a[i];
cout << endl << endl;
}
if(num == 5){
cout << "您选择了堆排序:" << endl << endl;
HeapSort(a, Max-1);
cout << "排序后:" << endl;
for(int i = 1; i <= Max-1; i++)
cout << left << setw(6) << a[i];
cout << endl << endl;
}
if(num == 6){
cout << "您选择了简单选择排序:" << endl << endl;
SelectSort(a, Max-1);
cout << "排序后:" << endl;
for(int i = 1; i <= Max-1; i++)
cout << left << setw(6) << a[i];
cout << endl << endl;
}
if(num == 7){
cout << "您已退出程序!";
return 0;
}
}
return 0;
}