一、堆排序
1、思想:堆其实就像是一个完全二叉树,只不过要求他的最大堆和最小堆满足所有子小于父或者子大于父,算法思想为,将排序的数组放在堆中,每次通过筛选(寻找最大堆的过程)确定出堆顶为整个数组的最大值,再把这个最大值和数组最后一个元素交换,再在n-1个元素中筛选找到整个数组最大值和倒数第二个元素交换,直到最后只剩下一个元素,整体就是非递减的。
2、时间复杂度:其最坏的时间复杂度也是O(nlogn),这也是堆排序胜于快速排序之处。
3、实现代码:
#include <iostream>
using namespace std;
void HeapAdjust(int *h,int s,int m){
int rc = h[s];
for(int j=2*s;j<=m;j=j*2){
if(j<m&&h[j+1]>h[j]) j++;
if(rc>h[j]) break;
h[s]=h[j];
s=j;
}
h[s]=rc;
}
void Heapsort(int *h,int n){
for(int i=n/2;i>0;i--) HeapAdjust(h,i,n);
for(int i =n;i>1;i--){
int c = h[i];
h[i]=h[1];
h[1]=c;
HeapAdjust(h,1,i-1);
}
}
int main(){
int n;
cin>>n;
int a[100];
for(int i =1;i<=n;i++){
cin>>a[i];
}
Heapsort(a,n);
for(int i =1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
二、归并排序
1、与快速排序不同的是,归并排序采用先分解再递归的方式,加入有n个子序列(这个n一开始为整个数组的大小,然后在合并的过程中慢慢变小,直到最后整体有序),然后将相邻的两个合并知道最后整体有序。
2、实现代码:
这里的代码有问题,希望能有大神指点,是merge的问题:
#include <iostream>
using namespace std;
void merge(int a[],int t[],int first,int mid,int last){
int i = first;
int j = mid+1;
int n =last;
int k = 0;
while(i<=mid&&j<=n){
if(a[i]<a[j]) t[k++]=a[i++];
else t[k++]=a[j++];
}
while(i<=mid){
t[k] = a[i];
k++;
i++;
}
while(j<=n){
t[k] = a[i];
k++;
j++;
}
for(int x = 0;x<k;x++){
a[first+x]=t[x];
}
}
void mergesort(int a[],int t[],int first,int last){
if(first<last){
int mid =(first+last)/2;
mergesort(a,t,first,mid);
mergesort(a,t,mid+1,last);
merge(a,t,first,mid,last);
}
}
int main(){
int n;
cin>>n;
int a[100];
for(int i =1;i<=n;i++){
cin>>a[i];
}
int t[100];
//merge(a,t,0,mid,n-1);
mergesort(a,t,1,n);
for(int i = 1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
3、时间复杂度:合并为n,分解要logn,所以时间复杂度为O(nlogn)
三、基数排序
1、算法思想:
这个适用于多关键字的排序。有两种排序方法,即MSD和LSD,MSD按照从主关键字到次关键字排序,LSD按照从次关键字到主关键字排序。基数排序主要采用的是LSD。采取先分配再收集的思想。分配的过程是将记录按照次关键字分配到radix个桶中,收集的过程为再将所有的桶连接起来。使用循环让所有关键字都能先分配再收集。
2、时间复杂度:O(d(n+rd)):d为关键字的个数,rd为每个关键字的范围,n为数组元素个数
3、算法框架:
void distribute(int *a,int key);
void collection(int *a,int key);
int main(){
int keynum;
int a[];
for(1..i..keynum){
distribute(a,i);
collection(a,i);
}
}
这几天终于都更完了。。。不过还是要好好再看一遍掌握牢固才更好。