复习排序这一章时,感觉内容很多很杂乱,加上代码听得半懂不懂,于是就来总结一下。前几天状态不在线,回家休息了两天,空了三天节奏。4.14写完这篇继续赶进度了,争取今天写完内部排序的习题,学完外排,结束DS了。
void insert_directly(int A[],int n){
int i,j,temp;
for(i=1;i<n;i++){
if(A[i]<A[i-1]){
temp = A[i];
for(j = i-1;j>=0 && A[j]>temp;--j){
A[j+1] = A[j];//所有大于temp(第i个)的都向后移一位(给第i个留位置插入)
}
A[j+1] = temp;
}
}
}//(没有用哨兵)
void insert_inhalf(int A[],int n){
int i,j,low,mid,high;
for(i=2;i<n;i++){
A[0] = A[i];//哨兵A[0]保存待插入元素A[i]
low = 1;
high = i-1;
while(low<=high){
mid = (low+high)/2;
if(A[mid]>A[0]){//查左子表 注意这里,即使A[mid]和A[0]想相同,也要再查找一次,目的是保证算法的稳定性。直到low>high,才停止循环
high = mid - 1;
} else
low = mid + 1;//查右子表
}
for(j=i-1;j>=high+1;--j){//将[low,i-1]内的元素全部右移
A[j+1] = A[j];
}
A[high+1] = A[0];
}
}
void shellsort(int A[],int n){
int d;//增量
int i,j;
for(d = n/2; d>=1; d=d/2){//增量变化
for(i=d+1; i<n; ++i){//轮流处理不同子表
if(A[i]<A[i-d]){
A[0] = A[i];//只是暂存在A[0],不是哨兵
for(j=i-d; j>0 && A[0]<A[j]; j-=d)//相当于在每个子表进行直接插入排序
A[j+d] = A[j];
A[j+d] = A[0];
}
}
}
}
void swap(int &a,int &b){
int t;
t = a;
a = b;
b = t;
}
void BubbleSort(int A[],int n){
for(int i=0;i<n-1;i++){
bool 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==false)//本趟没有发生交换,说明表已经有序
return;
}
}
int Partition(int A[],int low,int high){//用第一个元素将待排序序列划分为两部分
int pivot = A[low];//第一个元素作为枢轴
while(low<high){
while(low<high && A[high]>=pivot){
high = high - 1;
}
A[low] = A[high];//比枢轴小的元素前移
while(low<high && A[low]<=pivot){
low = low + 1;
}
A[high] = A[low];//比枢轴大的元素后移
}
A[low] = pivot;
return low;
}
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);//划分右子表
}
}
void SelectSort(int A[],int n){
for(int i=0;i<n-1;i++){
int min = i;//记录最小元素位置
for(int j=i+1;j<n;j++){
if(A[j]<A[min])
min = j;
}
if(min != i)
swap(A[i],A[min]);
}
}
void HeadAdjust(int A[],int k,int len){//将k为跟的子树调整为大根堆
A[0] = A[k];//A[0]暂存子树的根节点
for(int i=2*k; i<=len; i*=i){//沿k较大的子节点向下筛选
if(i<len && A[i]<A[i+1])
i++;//取k较大的孩子结点的下标
if(A[0]>A[i])
break;//当前跟结点比孩子大,不用调整
else{
A[k] = A[i];//较大的孩子结点换到父节点
k = i;
}
}
A[k] = A[0];//被筛选结点的位置放在最终位置
}
void BuildMaxHeap(int A[],int len){//建立大根堆
for(int i=len/2;i>0;i--)//从后往前每个分支结点,将其子树调整为大根堆
HeadAdjust(A,i,len);
}
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);//剩余待排序元素整理成堆
}
}
int *B = (int *) malloc(7 * sizeof (int));
void Merge(int A[],int low,int mid,int high){
int i,j,k;
for(k=low; k<=high; k++){
B[k] = A[k];//A中的所有元素赋值于B
}
for(i=low,j=mid+1,k=i; i<=mid&&j<=high; k++){//分成两组,i初值为第一组的第一个元素,j初值为第二组的第一个元素,第一组从[1,mid],第二组[mid+1,high]
if(B[i]<=B[j]){
A[k] = B[i];//A[k]是排序后的数组
i++;
}
else{
A[k] = B[j];
j++;
}
}
while(i<=mid)//说明for循环是因为j>high而结束,第二个表检测完,则后续把第一个表的剩余元素全加进来即可
A[k++] = B[i++];
while(j<=high)
A[k++] = B[j++];
}
void MergeSort(int A[],int low,int high){
if(low<high){
int mid = (low+high)/2;//从中间划分
MergeSort(A,low,mid);//递归左半部分 归并排序
MergeSort(A,mid+1,high);//递归右半部分,归并排序
Merge(A,low,mid,high);//归并排好序的两部分
}
}