排序算法总结

最近为找工作,开始复习基本的算法和数据结构,由于平时除了看书,还有做项目,所以就安排晚上睡觉前复习一下基础理论。经过一周多的时间,终于把最基本的排序算法的理论和实现搞完了。记录下复习结果,方便以后参考。

在此声明:因为好长时间没有看排序算法了,有些算法理论记得不太清楚,参考了MoreWindows的一些关于排序算法博客。

如果需要了解更详细的排序算法的理论,可以关注MoreWindows的blog:http://blog.csdn.net/morewindows

/* 	冒泡法排序
** 	冒泡法原理:重复的查看要排序的数列,比较相邻的两个数,如果他们的次序不对就相互交换,
**	直到没有需要交换的相邻的两个数为止。
** 	时间复杂度为O(n^2)
** 	空间复杂度为O(1)
**/
void swap(int &x, int &y)
{
	x = x^y;
	y = x^y;
	x = x^y;
}

void bubble_sort(int *array,int n)
{	
	int i,j;
	for(i = 0; i<n-1;i++)      //注意最好写成 i<n-1,而不是 i<n;虽然对结果没有影响
		for(j = 1; j<n-i;j++)
			if(array[j-1] > array[j])		//compare array[j-1] to array[j]
				swap(array[j-1],array[j]);
		/*	{
				int temp = array[j];
				array[j] = array[j-1];
				array[j-1] = temp; 
			}
			*/
}
/*	插入法排序
**	原理:插入法排序就是将一个数插入到一个有序的数列中,
**	时间复杂度: O(n^2)
** 	空间复杂度: O(1)
*/
void insert_sort(int array[],int len)
{
	int i,j,temp;
	for(i = 1; i < len ; i++)
	{
		temp = array[i];   		 	//保存需要插入的数
		for( j = i-1; j>=0; j--)
		{
			if(array[j] <= temp )  
				break;		//当满足 temp <array[j+1] && temp > array[j],退出循环
			array[j+1] = array[j];
		}
		//也可以这样写
		#if 0
		j=i-1;
		while(j>=0 && array[j] > temp) //
		{
			array[j+1] = array[j];
		}
		#endif
		array[j+1] = temp;		//在array[j+1] 的位置上插入 array[i]
	}
}
/*选择排序
**思想原理:从序列中选择一个最大(或者最小)的数放在序列的最后(或者开头)。
**选择排序是个不稳定的排序,
**时间复杂度:O(n^2)
**空间复杂度O(1)
*/

//#code1
void select_sort(int A[],int n)
{
	int temp,index;
	for(int i=n-1;i>0;i--) //note the boundary
	{
		index = i;
		for(int j = i-1; j>=0;j--)
		{
			if(A[j] > A[index])
				index = j;
		}
		temp = A[i];
		A[i] = A[index];
		A[index] = temp;
	}
}
/*
//#code 2
void SelectSort(int A[], int n)
{
	int temp , index;
	for(int i=0;i<n-1;i++)
	{
		index = i;
		for(int j= i+1;j<n;j++)
			if(A[j]<A[index])
				index = j;
		temp = A[i];
		A[i] = A[index];
		A[index] = temp;
	}
}
*/

/* 快速排序
** 基本思想:从序列中选定一个数 key,然后将序列分成两部分,左边部分的所有的数
** 都不大于key,而右边的数都不小于key,然后对这两部分的数分别进行快速排序,整个
** 排序可以通过递归的方法。
** 时间复杂度:平均O(nlog(n)),最坏O(n^2)(逆序);
** 空间复杂度:O(1)。
*/

void quick_sort(int A[], int n)
{
	int i = 0, j = n-1;
	int val = A[0];
	if(n>1)    			//if array is empyt or just a elemnt,it doesn't need sort
	{
		while(i<j)   //
		{
			for(;j>i;j--) //find the first element which is smaller than val from back.
				if(A[j] < val)
				{
					A[i] = A[j];
					break;
				}
			for(;i<j;i++)//find the first element which is greater than val from front.
			{
				if(A[i] > val)
				{
					A[j] = A[i];
					break;
				}
			}
		}
		
		A[i] = val;		//A[0] ~ A[i-1] <= val, A[i+1] ~ A[n] >= val
		quick_sort(A,i); //sort the first i elements,A[0] ~ A[i-1]
		quick_sort(A+i+1,n-i-1); //sort the last (n-i-1) elements,A[i+1] ~ A[n-1]
	}
}

/*	归并排序
**	基本思想:把待排序的序列分成两个子序列,每个子序列都是有序的,然后合并两个有序的子序列。
**	该算法是采用分治策略的典型应用,首先将原序列分成两个子序列,然后对子序列再分成两个子序列,
**	直到子序列有序(一般只有一个元素),然后在将相邻的两个有序的序列合并(2路-合并),直到整个
**	都有序为止。
**	时间复杂度:O(nlog(n)) 空间复杂度:O(n)
*/
void Merge(int *A, int p, int q, int r)
{
	int m = q-p+1, n = r-q;
	int i=0,j=0,k=0;
	int *r1 = (int *) malloc(sizeof(int) * (m));
	int *r2 = (int *) malloc(sizeof(int) * (n));
	//initialize r1 & r2
	for(i=0; i<m; i++)
		r1[i] = A[p+i];
	for(i=0 ; i<n; i++)
		r2[i] = A[q+i+1];
	i=0;
	j=0;
	k=0;
	while(i<m || j<n)
	{
		if(i<m && j<n)
		{
			if(r1[i] > r2[j])
				A[p+k++] = r2[j++];
			else
				A[p+k++] = r1[i++];
		}
		else if(i>=m)
			A[p+k++] = r2[j++];
		else
			A[p+k++] = r1[i++];
	}
	free(r1);
	free(r2);
}

void MergeSort(int *A,int p , int r)
{
	if(p<r)
	{
		int q = (p+r)/2;
		MergeSort(A,p,q);
		MergeSort(A,q+1,r);
		Merge(A,p,q,r);
	}
}

/* 	计数排序
** 	要求:	需要输入线性序列都在有限序列集 S 中。
** 	基本思想:对于序列中任意一个元素A[i],找出序列中小于A[i]的元素个数k,那么就可以
** 	确定A[i]在序列中位置为k+1。需要注意的是可能有重复的数。
**	时间复杂度:O(n+k)(k为序列中数值的范围),空间复杂度:O(k)
*/
void count_sort(int A[], const int max,const int n) //max为数组A中最大的数,n为数组A的元素个数
{
	int i,j;
	int *B = (int *)malloc(sizeof(int)*(max+1)); //0~max,总共有(max+1)个数
	memset(B,0,(max+1)*sizeof(int));
	for(i=0;i<=max;i++)
		printf("%d ",B[i]);
	printf("\n");
	for(i=0;i<n;i++)
		B[A[i]]++;  //统计排序的个数
	j=0;
	for(i=0;i<=max;i++)
	{
		int temp = B[i];
		while(temp--)		//B[i]表示在A中有B[i]个元素 i
			A[j++] = i;
	}
	free(B);
} 
/* 	希尔(shell)排序
**	基本思想:将整个待排序的序列分成若干子序列(相隔某一步长的元素),然后对每个子序列进行简单插入排序,再缩小
**	步长,继续对子序列进行插入排序,直到子序列基本有序,对整个序列进行一次排序,就可以完成排序
**  时间复杂度: O(n^(3/2))
** 	空间复杂度: O(1)
*/
void shell_sort(int a[], int n)
{
	int i,j,steps;
	for(steps = n/2 ; steps > 0 ; steps /=2)
	{
		for(i=steps;i<n;i += steps) //从第二个元素开始,每次和之前的元素比较
		{
			if( a[i] < a[i-steps])
			{
				int temp = a[i];
				j = i-steps;
				while(j>=0 && a[j] > temp)
				{
					a[j+steps] = a[j];
					j -= steps;
				}
				a[j+steps] = temp;
			}
		}
	}
}

/* 	堆排序
**	思想原理:首先要建立最小堆(或者最大堆),然后交换a[0] 和 a[n-1]
**	然后再维护a[0] 到 a[n-2]为最小堆(或者最大堆)
** 	时间复杂度: O(nlog(n))
** 	空间复杂度: O(1)
*/
/* 最小堆*/
void minHeap(int a[], int n ,int i)
{
	int j = 2*i + 1;
	while(j<n)
	{
		if( j+1 < n && a[j] > a[j+1])
			 j++;
		if(a[i] <= a[j])
			break;
		int temp = a[i];
		a[i] = a[j];
		a[j] = temp;
		i = j;
		j = 2*i+1;
	}
}
/*最大堆*/
void maxHeap(int a[],int n,int i)
{
	int j= 2*i+1;
	while(j<n)
	{
		if(j+1 < n && a[j+1] > a[j])
			j++;
		if(a[i]>=a[j])
			break;
		swap(a[i],a[j]);  //这里采用在<utility.h>中的库函数
		i = j;
		j = 2*i+1;
	}
}
/*建堆*/
void create_minheap(int a[] , int n)
{
	for(int i = (n-1)/2; i>=0;i--)
		maxHeap(a,n,i);
		//minheap(a,n,i);
}

/*堆排序*/
void heap_sort(int a[],int n)
{
	create_minheap(a,n);
	for(int i = n-1;i>0;i--)
	{
		swap(a[0],a[i]);
		maxHeap(a,i,0);
		//minHeap(a,i,0);
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值