常见排序算法总结

【转自:http://blog.csdn.net/cxf7394373/article/details/6364702

【另外参考:浅谈算法和数据结构: 二 基本排序算法】(博客园的文章,推荐)


前言    

     学了数据结构几年了,回头看看数据结构里基础算法,都忘光了...

     昨天,舍友去腾讯搜索部门面试,一面二面全是算法,虽然不尽是数据结构基础算法,却也以此为基础,一番讨论之后,发现自己只能说出一些算法的大概,不能给出细节内容,遂感悲催!期间讨论了快速排序的性能提高的随机算法,并利用它选择中位数,使得时间复杂度为O(n),我以前写过这个算法,却怎么也记不起细节...

     今天,重温所有排序算法,慰藉吾心!!程序员伤不起啊伤不起!!

  排序算法     

     常见排序算法有简单排序(直接插入排序、冒泡排序、简单选择排序),希尔排序,快速排序,堆排序,基数排序等几种,时间复杂度可以总结如下:

     

  简单排序

    需要一个辅助空间,时间复杂度皆为O(n*n)

  

//直接插入排序
void insertSort(int L[],int n)
{
	int i, j;
	int x;

	for (i = 1;i < n;i++)
	{
		j = i - 1;
		x = L[j+1];
		for (;j >= 0 && x < L[j];j--)
		{
			L[j +1] = L[j];
		}
		L[j+1] = x;
	}
}
//冒泡排序
void upSort(int L[],int n)
{
	int i,j;

	int temp;
	for (i = n-1;i > 0;i--)
	{
		for (j = 0;j < i;j++)
		{
			if(L[j] > L[j+1])
			{
				temp = L[j];
				L[j] = L[j+1];
				L[j+1] = temp;
			}
		}
	}
}
//简单选择排序
void selectSort(int L[],int n)
{
	int i,j;
	int temp;
	for(i = 0; i < n;i++)
	{
		int k = i;
		for (j = i;j < n;j++)
		{
			if(L[j] < L[k])k = j;
		}
		temp = L[i];
		L[i] = L[k];
		L[k] = temp;
	}
}

  希尔排序

      基本思想:先将整个待排序序列分割成若干子序列,再分别进行直接插入排序,待整个序列基本有序时在对整体进行一次直接插入排序。

//希尔排序
void shellSort(int L[],int n)
{
	int i,j,d;
	int x;
	d = 1;
	while (3*d < n)d = d*3 + 1;
	
	while (d > 0)
	{
		for (i = d;i < n;i++)
		{
			for (j = i - d,x = L[i];j >= 0 && x < L[j];j =j -d)
			{
				L[j + d] = L[j];
			}
			L[j+ d] = x;
		}
		d = d / 3;
	}
}


 快速排序

     快速排序是对冒泡排序的改进,基本思想是通过一趟排序将待排记录分成两个独立的部分,其中一部分的记录都小于哨兵位的数值,另一部分都大于哨兵位的值,然后继续对两部分分别快速排序。可见快速排序的关键在于寻找哨兵位

void QuickSort(int L[],int first,int last)
{
	if (first < last)
	{
		int split = Partition(L,first,last);
		QuickSort(L,first,split - 1);
		QuickSort(L,split + 1,last);
	}
	return;
}
int Partition(int L[],int first,int last)
{
	int pivot = L[first];
	
	while (first < last)
	{
		while (first < last && L[last] >= pivot)last--;
		L[first] = L[last];
		while (first < last && L[first] < pivot) first++;
		L[last] = L[first];
	}
	L[first] = pivot;
	return first;
}


 堆排序

     堆排序的关键是对记录所对应的完全二叉树进行调堆操作。需要解决的两个问题是:(1) 如何由一个无序序列建立一个堆 (2)如何在输出堆顶元素后调整剩余元素形成一个新的堆。过程示例如下:

   

void heapAjust(int L[], int k,int n)
{
	int i;
	int x;
	
	x = L[k];
	i = 2*k;
	while (i < n)
	{
		if (i < n && L[i] < L[i + 1])i++;
		if(x >= L[i])break;
		L[k] = L[i];
		k = i;
		i = 2*i;
	}
	L[k] = x;
}
void heapSort(int L[],int n)
{
	int i;
	int x;
	for (i = n / 2 - 1;i >= 0;i--)
	{
		heapAjust(L,i,n);
	}
	for (i = n-1;i >= 1;i--)
	{
		x = L[0];
		L[0] = L[i];
		L[i] = x;
		heapAjust(L,0,i-1);
	}
}

  归并排序

     基本思想:将两个或两个以上的有序表组合成一个新的有序表

//归并排序
void mergeSort(int L[],int n)
{
	int a,b,c,step;

	step = 1;
	while (step < n)
	{
		a = 0;
		while (a < n)
		{
			c = a + step - 1;
			if (c >= n)break;
			b = c + step;
			if (b >= n)b = n-1; 
			merge(L,a,c,b,n);
			a = b + 1;
		}
		step = step * 2;
	}
}
void merge(int L[], int low, int mid, int high,n)
{
        int i, k;
        int *temp = (int *) malloc((high-low+1) * sizeof(int)); //申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
        int begin1 = low;
        int end1 = mid;
        int begin2 = mid + 1;
        int end2 = high;
 
        for (k = 0; begin1 <= end1 && begin2 <= end2; ++k)  //比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
                if(L[begin1]<=L[begin2])
                        temp[k] = L[begin1++];
                else
                        temp[k] = L[begin2++];       
        if(begin1 <= end1) //若第一个序列有剩余,直接拷贝出来粘到合并序列尾
                memcpy(temp+k, L+begin1, (end1-begin1+1)*sizeof(int));
        if(begin2 <= end2) //若第二个序列有剩余,直接拷贝出来粘到合并序列尾
                memcpy(temp+k, L+begin2, (end2-begin2+1)*sizeof(int));
        memcpy(L+low, temp, (high-low+1)*sizeof(int));//将排序好的序列拷贝回数组中
        free(temp);
}


参考


     [1]  算法导论第二部分

     [2]  数据结构,严蔚敏

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值