1. 直接插入排序(有序表的扩大)
void InsertSort(int *A,int n){
int i,j;
for(i=2;i<=n;i++){ //从第二个元素开始遍历n-1次,插入到前面的有序数组中
A[0]=A[i]; //存储待插入元素
for(j=i-1;A[0]<A[j];--j)
A[j+1]=A[j]; //将大于待插入元素的元素往后移动一位,空出插入位置
A[j+1]=A[0]; //插入元素
}
}
折半插入排序
void InsertSort(int *A,int n){
int i,j,low,high,mid;
for(i=2;i<=n;i++){ //从第二个元素开始遍历n-1次,插入到前面的有序数组中
A[0]=A[i]; //存储待插入元素
low=1;high=i-1;//有序数组的左右两端指针
while(low<=high){ //折半查找出待插入位置
mid=(low+high)/2;
if(A[mid]>A[0]) high=mid-1;
else low=mid+1;
}
for(j=i-1;j>=high+1;--j) //跳出条件直接使用了插入位置high
A[j+1]=A[j]; //将大于待插入元素的元素往后移动一位,空出插入位置
A[j+1]=A[0]; //插入元素
}
}
希尔排序
void InsertSort(int *A,int n){
int i,j;
for(dk=n/2;dk>=1;dk=dk/2) //步长每次缩小一半直至变为1
for(i=dk+1;i<=n;i++){ //从第1+dk个元素开始遍历,插入到前面的有序非连续数组中
if(A[i]<A[i-dk]){ //有序则跳过该次循环
A[0]=A[i]; //存储待插入元素
for(j=i-dk;j>0&&A[0]<A[j];j-=dk) //变换的步长为dk
A[j+dk]=A[j]; //将大于待插入元素的元素往后移动dk位,空出插入位置
A[j+dk]=A[0]; //插入元素
}
}
}
2. 冒泡排序(逐个冒出最值)
void BubbleSort(int *A,int n){
for(int i=0;i<n-1;i++){ //遍历n-1趟
flag = false; //设置标志位,当数组有序即一趟没发生交换时,跳出循环
for(int j=n-1;j>i;j--){ //从后往前交换
if(A[j-1]>A[j]){ //冒出最小值
swap(A[j-1],A[j]);
flag=true;
}
}
if(flag==flase) return;
}
}
3. 快速排序(枢轴递归分治)
void QuickSort(int *A,int low,int high){
if(low>=high) return;
int pivot_pos=Partition(A,low,high); //使枢轴右侧大于左侧并返回枢轴位置
QuickSort(A,low,pivot_pos-1); //递归枢轴左半边
QuickSort(A,pivot_pos+1,high); //递归枢轴右半边
}
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[low]=pivot;//枢轴元素放回枢轴位置
return low;//返回枢轴位置
}
4. 简单选择排序(选出最值)
void SelectSort(int *A,int n){
for(int i=0;i<n-1;i++){ //从前往后,进行n-1趟遍历
min = i; //记录这趟遍历最小值位置
for(j=i+1;j<n;j++) //选出该趟遍历最小元素
if(A[j]<A[min]) min=j; //选出最小值
if(min!=i) swap(A[i],A[min]); //如果最小元素不是待插入位置,则交换
}
}
5. 堆排序(利用堆的性质不断调整和冒出最值)
void HeapSort(int *A,int len){
BuildMaxHeap(A,len); //建立大根堆
for(int i=len;i>1;i--){ //n-1趟交换和建堆过程
swap(A[i],A[1]); //输出堆顶元素(和堆底元素交换)
HeadAdjust(A,1,i-1); //把剩余i-1个元素调整成堆
}
}
void BuildMaxHeap(int *A,int len){
for(int i=len/2;i>0;i--) //从i=~n/2~1,反复调整堆
HeadAdjust(A,i,len); //调整算法把左右子树皆为堆的树调整成堆
}
void HeadAdjust(int *A,int k,int len){
//将元素k为根的子树进行调整
A[0]=A[k]; //A[0]暂存子树根节点
for(int i=2*k;i<=len;i*=2){ //该循环是为了将根节点值不断往下送
if(i<len&&A[i]<A[i+1]) i++; //若右节点大,指针移动到右节点
if(A[0]>A[i]) break; //调整结束,即根节点大于两子节点
else{ //否则继续将根节点的值往下送
A[k]=A[i]; //根节点位置换成较大子节点的值
k=i; //记录子节点指针作为新的根节点或终止节点
}
}
A[k]=A[0]; //循环结束终止节点赋往下送根节点值
}
6. 归并排序(分治归并有序子表)
void MergeSort(int *A,int low,int high){
if(low>=high) return;
int mid = (low+high)/2; //数组分成两部分
MergeSort(A,low,mid); //对左边递归排序使其有序
MergeSort(A,mid+1,high); //对右边递归排序使其有序
Merge(A,low,mid,high); //合并两有序表
}
void Merge(int *A,int low,int mid,int high){
for(int k=low;k<=high;k++){
B[k]=A[k]; //复制出一个新的数组作为比较
for(int i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){ //从左往右,两个指针对两数组逐个对比
if(B[i]<B[j]) A[k]=B[i++]; //将小的值赋回给A,并移动指针
else A[k]=B[j++];
}
while(i<=mid) A[k++]=B[i++]; //将没复制完的复制过去
while(j<=high) A[k++]=B[j++]; //将没复制完的复制过去
}
}