排序算法之堆排序、基数排序和归并排序的思想及部分实现

4 篇文章 0 订阅
4 篇文章 0 订阅

一、堆排序

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);
}

这几天终于都更完了。。。不过还是要好好再看一遍掌握牢固才更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值