选择排序
思想:每一趟在待排序元素中选取关键字最小或最大的元素加入有序子序列
简单选择排序
选择最小的,n个元素需要处理n-1躺
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++) //在[i,n-1]中找到最小的值
if(A[j]<A[min]) min=j;
if(min!=i) swap(A[j],A[min]);
}
}
void swap(int &a,int &b){
int temp =a;
a=b;
b=temp;
}
-
空间复杂度:O(1) 时间复杂度:O(n平方) 不稳定
堆排序
大根堆:完全二叉树中,根>=左右
小根堆:完全二叉树中,根<=左右
如何由一个无序序列建成一个堆?
如何在输出堆顶元素后,调整剩余元素为一个新的堆?
//建立大根堆
void BuildMaxHeap(int A[],int len){
//找到最后一个非叶子节点进行处理
for(int i=len/2;i>0;i--){ //len/2找到最后一个非叶子节点
HeadJust(A,i,len); //调整成大根堆
}
}
void HeadJust(int A[],int i,int len){
A[0]=A[i];
for(int k=2*i;k<=len&&;k=k*2){ //比较A[i]的孩子做交换,可能有很多层孩子
if(k<len&&A[k]<A[k+1]) k++; //对比当前处理的根节点的左右孩子谁大,i<len保证i节点是有右兄弟的
if(A[k]<=A[0]){ //证明根节点比较大,不用交换
break;
}else{
A[i]=A[k]; //根节点小,交换
i=k;
}
}
A[i]=A[0];
}
void HeapSort(int A[],int len){
BulidMaxHeap(A,len);
for(int i =len;i>0;i++){ //n-1趟的交换和建堆的过程
A[i]=A[1]; //交换堆顶与堆底
HeadJust(A,1,i-1); //把剩余的待排序元素整理成堆
}
}
-
空间复杂度:O(n平方) 时间复杂度:最好:O(nlogn) 最坏:O(nlogn) 平均:O(nlogn) 不稳定
归并排序
把两个或多个已经有序的序列合并成一个
核心:把数组内的两个有序序列归并为一个
Elemtype *B=(ElemType*) malloc((n+1)*sizeof(ElemType));
void Merge(ElemType A[],int low,int mid,int high){
int k;
//两段必须各自有序
for(int i=low;i<=high;i++){
A[i]=B[i]; //将A拷贝到B
}
for(i=low,j=mid+1;k=low;i<=mid&&j<=high;k++){ //比较两段的大小
if(B[i]>B[j]) A[k]=B[j++]; //前面一半第一个大于后面一半的第一个,修改A[]的值为小的,并且后面一半的指针后移一位
else if(B[i]<=B[j]) A[k]=B[i++]; //前<后,修改A[]的值为小的,且前一半的指针后移一个
}
while(j<=high) A[k++]=B[j++]; //如果后半段还没遍历完,就把剩下的全加到A里面去
while(i<=mid) A[k++]=B[i++]; //前
}
void MergeSort(ElemType 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); //归并
}
}
[8, 3, 1, 7, 0, 4, 9, 2, 6, 5] | | [8, 3, 1, 7, 0] | [4, 9, 2, 6, 5] | Divide Phase / | \ | [8, 3] | [1, 7, 0] | [4, 9] | [2, 6, 5] | / | | | | [8] | [3] | [1, 7] [0] | [4] [9] | [2] [5,6] Divide Phase \ / \ / | | / | [8, 3] [0, 1, 7] [4, 9] [2, 5, 6] Merge Phase \_______|_________/ \_______/ | | [0, 1, 3, 7, 8] [2, 4, 5, 6, 9] Merge Phase \__________________________/ | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Merge Phase
-
空间复杂度:O(n) 时间复杂度:最好:O(nlogn) 最坏:O(nlogn) 平均:O(nlogn) 稳定
基数排序(桶、箱排序)
基本思想:分配+收集
假设有以下未排序的整数数组:[170, 45, 75, 90, 802, 24, 2, 66] 第一次迭代(按照个位) 桶0:170, 90 桶1: 桶2:802,2 桶3: 桶4:24 桶5:45, 75 桶6:66 桶7: 桶8: 桶9: 得到数组:[170, 90, 802, 2, 24, 45, 75, 66] 第二次迭代(按十位) 桶0:802,002, 024 桶1: 桶2: 桶3: 桶4:045, 066 桶5:075 桶6: 桶7: 桶8:090 桶9:170 得到数组:[802, 002, 024, 045, 066, 170, 075, 090] 第三次迭代: 桶0:002, 024, 045, 066, 075, 090 桶1:170 桶2: 桶3: 桶4: 桶5: 桶6: 桶7: 桶8: 桶9:802 得到数组:[002, 024, 045, 066, 075, 090, 170, 802]
-
最好情况 O(n+m) 最坏情况O(k(n+m)) 平均情况 O(k(n+m)) 空间复杂度O(n+m) 稳定
k:关键字的个数(分配多少趟) m:桶的个数(多少个桶就要收集多少次) n是元素的个数(要扔多少个)