现在的位置: 首页 > 综合 > 正文

排序-归并、快排、插入、堆、希尔排序

2012年06月05日 ⁄ 综合 ⁄ 共 2545字 ⁄ 字号 评论关闭

以上排序都属于内部排序, 希尔排序属于插入排序,堆排序属于选择排序,

对排序的各种实现:直接上代码:

#include <iostream>
#include <stdio.h>
using namespace std;
int a[1000];
long sum=0;
void swap(int x,int y)
{
	int temp;
	temp=a[x];
	a[x]=a[y];
	a[y]=temp;
}
void merge(int x,int y)//归并
{
	int mid=(x+y)/2;int k=x;
	int left[505];
	int right[505];
	int n1=mid-x+1;
	int n2=y-mid;
	for (int i=0;i<n1;i++)
	{
		left[i]=a[x++];
	}
	for (int j=0;j<n2;j++)
	{
		right[j]=a[x++];
	}
	i=j=0;
	while(i<n1&&j<n2)
	{
		if (left[i]<right[j])
		{
			a[k++]=left[i++];
		}
		else
		{
			a[k++]=right[j++];
			sum+=n1-i;//此处可以记录交换的次数
		}
	}
	while (i<n1)
	{
		a[k++]=left[i++];
	}
	while (j<n2)
	{
		a[k++]=right[j++];
	}
}
void mergesort(int x,int y)//时间复杂度是O(nlogn)
{
	if (x<y)
	{
		int mid=(x+y)/2;
		mergesort(x,mid);
		mergesort(mid+1,y);
		merge(x,y);
	}
}
void insertsort(int n)//时间复杂度O(n^2)
{
	int i,j,temp;
	for (i=0;i<n;i++)
	{
		temp=a[i];
		for (j=i;j>0&&a[j-1]>temp;j--)//在i元素前的所有比i大的元素向后移动一个位置 为i空出一个位置 
		{
			a[j]=a[j-1];
		}
		a[j]=temp;
	}
}
void quicksort(int x,int y)//时间复杂度O(nlogn)
{
	if (x>=y) return ;
	int sign=a[y];
	int low=x-1;
	int high=y;
	while(low<high)
	{
		while (low<y&&a[++low]<sign);//low指针向后找到第一个比sign小的
		while (high>0&&a[--high]>sign);//high指针向前找到第一个比sign大的
		if (low<high)  swap(low,high);
	}
	swap(y,low);
	quicksort(x,low-1);
	quicksort(low+1,y);
}
//堆是完全二叉树,子节点的父节点是(i-1)/2
//父节点的子节点是i*2+1,i*2+2
void heap(int x,int y)
{
	int i,j;
	int temp=a[x];
	while (x<y/2)
	{
		int k=2*x+1;
		if (k+1<y&&a[k]<a[k+1]) ++k;//在子节点中找一个大的与根值互换
		if (temp>a[k]) break;
		a[x]=a[k];
		x=k;
	}
	a[x]=temp;
}
//堆的一个性质:最大元素在根处,最小元素是某个叶节点
void heapsort(int n)//最坏的情况下,时间复杂度O(nlogn)
{
	int i;
	int x=n/2-1;
	for (i=x;i>=0;i--)//更新所有的根节点,使形成堆
	{
		heap(i,n);
	}
	for (i=n-1;i>0;i--)//堆排序 每次更新到最下面的是最大的树
	{
		swap(0,i);//0-i是具有堆性质
		heap(0,i);
	}
}
void shillsort(int n)
{
	int i,j;
	int t=1;
	while (t<n/4) t=t*2+1;//设置增量
	while (t>0)
	{
		for (i=t;i<n;i++)//对每一块排序
		{
			j=i;
			int d=a[i];
			while(j>=t&&a[j-t]>d)
			{
				a[j]=a[j-t];
				j-=t;
			}
			a[j]=d;
		}
		t/=2;//增量变小(即合并过程)
	}
}
int length(int n)
{
	int i,l=1,p=10;
	for (i=0;i<n;i++)
	{
		while(a[i]>=p)
		{
			p*=10;
			l++;
		}
	}
	return l;
}
//基数排序是稳定排序
void radixsort(int n)
{
	int i,flag=1,j,k;
	int len=length(n);//确定关键字的个数
	int temp[1005];
	int cnt[10];
	for (i=0;i<len;i++)
	{
		for (j=0;j<10;j++)
		{
			cnt[j]=0;
		}
		for (j=0;j<n;j++)//按尾数确定分组(桶)
		{
			k=(a[j]/flag)%10;
			cnt[k]++;
		}
		for(j=1;j<10;j++)
		{
			cnt[j]=cnt[j]+cnt[j-1];
		}
		for (j=n-1;j>=0;j--)//根据桶确定新的顺序
		{
		    k=(a[j]/flag)%10;
			cnt[k]--;
			temp[cnt[k]]=a[j];
		}
		for (j=0;j<n;j++)
		{
			a[j]=temp[j];
		}
		flag*=10;//第一次从个位数排序,然后对十位数,以此类推、、、
	}
}
int main()
{
	//freopen("Input.txt","r",stdin);
	int n;
	while(cin>>n)
	{
		for (int i=0;i<n;i++)
		{
			cin>>a[i];
		}
		//mergesort(0,n-1);对两个有序序列进行归并的排序
		//insertsort(n);把比i小的元素前移一个位置,然后插入i
		//quicksort(0,n-1);左边都比右边小
		//heapsort(n);确定堆,更新堆底元素
		//shillsort(n);	以增量为分组排序
		//radixsort(n);以关键字排序
		for (int j=0;j<n;j++)
		{
			cout<<a[j]<<" ";
		}
	}
	return 0;
}

注:选择排序在最好的情况下的时间复杂度是O(N)

关于几种排序的一个形象效果图地址:

http://www.cnblogs.com/wangfupeng1988/archive/2011/12/26/2302216.html

抱歉!评论已关闭.