#define SUM 100
#include <iostream>
#include <vector>
#include <string>
#include <ctime>
using namespace std;
void InsertSort(int A[],int n){
int j;
for(int i=2;i<=n;i++){
if(A[i]<A[i-1]){
A[0]=A[i];
for(j=i-1;A[j]>A[0];j--){
A[j+1]=A[j];
}
A[j]=A[0];
}
}
cout<<"直接插入"<<endl;
for(int k=1;k<=n;k++){
printf("%-5d ",A[k]);
if(k!=0&&k%9==0) cout<<"\n";
}
}
void BinaryInsertSort(int A[],int n){
int j;
for(int i=2;i<=n;i++){
if(A[i]<A[i-1]){
A[0]=A[i];
int low=1,high=i-1;
while(low<=high){
int mid=(low+high)/2;
if(A[mid]>A[0]){
high=mid-1;
}else low=mid+1;
}
for(j=i-1;j>=high+1;j--){
A[j+1]=A[j];
}
A[high+1]=A[0];
}
}
cout<<endl<<"折半插入"<<endl;
for(int k=1;k<=n;k++){
printf("%-5d ",A[k]);
if(k!=0&&k%9==0) cout<<"\n";
}
}
void ShellSort(int A[],int n){
int j;
for(int dk=n/2;dk>=1;dk=dk/2){
for(int i=dk+1;i<=n;i++){
if(A[i]<A[i-dk]){
A[0]=A[i];
for(j=i-dk;j>0&&A[0]<A[j];j-=dk)
A[j+dk]=A[j];
A[j+dk]=A[0];
}
}
}
//选定相隔dk的两个元素进行比较,例如将1和51比较,2和52比较。。。
//以此类推之后将步长缩短一半,例如将1和26比较,2和27比较。。。
//到步长为1的时候序列基本有序,加少了移动的步骤
cout<<endl<<"希尔排序"<<endl;
for(int k=1;k<=n;k++){
printf("%-5d ",A[k]);
if(k!=0&&k%9==0) cout<<"\n";
}
}
void BubbleSort(int A[],int n){
int temp;
for(int i=n;i>=0;i--){//此处之所以是i=n是为了照顾之前的A[0]处为哨兵的设置
for(int j=i-1;j>=0;j--){
if(A[i]<A[j]){
temp=A[i];
A[i]=A[j];
A[j]=temp;
}
}
}
cout<<endl<<"冒泡排序"<<endl;
for(int k=1;k<=n;k++){
printf("%-5d ",A[k]);
if(k!=0&&k%9==0) cout<<"\n";
}
}
void produceRandomNumbers(int A[],const int start, const int end, const int amount) {
srand((unsigned)time(NULL));
for (int cnt = 1; cnt <= amount; ++cnt) {
A[cnt]=start + (rand() % (end - start));
}
}
int Partition(int A[],int low,int high){
int pivot=A[low];
while(low<high){
while(low<high&&A[high]>=pivot)
--high;
A[low]=A[high];
while(low<high&&A[low]<=pivot)
++low;
A[high]=A[low];
}
A[high]=pivot;//此时high=low,指向的位置就是pivot应该在的位置
return low;
}
/*
在执行过程中有两个指针分别是low和high,
和一个临时变量pivot用来记录当前排序的元素(就是在本次排序的目的就是将pivot插入到准确位置)
在开始执行时将pivot设置为A[low],然后从high到low之间遍历,如果发现有逆序元素就移到low上
再从low到high之间遍历,如果发现有逆序元素就移到high上
有点像将一个乱序表的第一个元素所在的位置清零,如果从high到low中发现逆序就将该逆序元素填到坑里
此时坑在较高位置
然后从low到high,如果发现逆序元素就把该元素填到坑里,该元素原本的位置即为坑,此时坑在较低位置
知道low=high时,此时low的位置就是pivot应该在的位置。一次排序结束。递归分段继续
*/
void QuickSort(int A[],int low,int high){
if(low<high){
int pivotpos=Partition(A,low,high);
QuickSort(A,low,pivotpos-1);
QuickSort(A,pivotpos+1,high);
}
}
int main(){
int A[SUM+1];//因为A[0]存放哨兵
produceRandomNumbers(A,1, 10000, SUM);
InsertSort(A,SUM);
produceRandomNumbers(A,1, 10000, SUM);
BinaryInsertSort(A,SUM);
produceRandomNumbers(A,1, 10000, SUM);
ShellSort(A,SUM);
produceRandomNumbers(A,1, 10000, SUM);
BubbleSort(A,SUM);
produceRandomNumbers(A,1, 10000, SUM);
QuickSort(A,0,SUM);
cout<<endl<<"快速排序"<<endl;
for(int k=1;k<=SUM;k++){
printf("%-5d ",A[k]);
if(k!=0&&k%9==0) cout<<"\n";
}
return 0;
}