关闭

各种排序算法总结

标签: 排序算法插入排序算法选择排序快速排序
665人阅读 评论(0) 收藏 举报
分类:

(注:以下所讲排序,以升序排序为例!)

选择排序:

作者思路:在一组数中,选择第一个数标记为最小值,在剩下的数中找比它小的数,若找到则交换两数,标记新的"最小值",然后继续往下找,这样一趟下来就可以找到一组数中第二小的值,第二次以第二个数作为最小值,如此循环下去。这是最简单、最基础的一种排序算法。


例子:13,34,18,9,12,34,100

第一次(i=0),以13为最小值,第一次算法结束:9,34,18,13,12,100

第二次(i=1),以34作为最小值,(18比它小,交换得)9,18,34,13,12,100——>(13比18小,交换)9,13,34,18,12,100——>结束得:9,12,34,18,13,100,此时 12已经是真正的次最小值。往后找不到比它还小的。

第三次(i=2),以34做为最小值,继续执行

。。。


时间复杂度: O(n * n);

代码:

void Swap(int a[], int i, int j)
{
	int tmp = a[i];
	a[i] = a[j];
	a[j] = tmp;
}

void SelectSort(int a[], int len) //O(n * n)
{
	int i = 0;
	int j = 0;
	int min = 0;
	
	for(i=0; i<len; i++)
	{	
		min = a[i];
		
		for(j=i+1; j<len; j++)
		{
			if(a[j] < min)
			{
				Swap(a, i, j);
			}
			min = a[i];
		}
	}
}

插入排序:

作者思路:插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。 

时间复杂度:O(n * n)


代码:

void InertionSort(int array[], int len) // O(n*n)
{
    int i = 0;
    int j = 0;
    int k = -1;
    int temp = -1;
    
    for(i=1; i<len; i++)
    {
        k = i;
        temp = array[k];
        
        for(j=i-1; (j>=0) && (array[j]>temp); j--)
        {
            array[j+1] = array[j];
            k = j;
        }
        
        array[k] = temp;
    }
}

冒泡排序:

作者思路:将被排序的记录数组R[1..n]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,就使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。


代码:

void BubbleSort(int a[], int len) //O(n * n)
{
	int i = 0;
	int j = 0;
	int k = 1;//标记,避免不必要的循环。
	
	for(i=0; i<len && k; i++)
	{	
		k = 0;
		
		for(j=len-1; j>i; j--)
		{
			if(a[j] < a[j-1])
			{
				Swap(a, j, j-1);
				k = 1;
			}
		}
	}
}

总结:上述三种排序算法都比较基础,也不难,关键要理解其思想;三种算法都是稳定算法(ps:什么是稳定算法,比如一组数中有两个一样的数 9,9*(加*以示区分) 排序后,两者的顺序不会变动 这样的算法是稳定的 )。


快速排序:

快速排序是一种排序算法,对包含n个数的输入数组,平均时间为O(nlgn),最坏情况是O(n^2)。
通常是用于排序的最佳选择。因为,基于比较的排序,最快也只能达到O(nlgn)。

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

步骤为:

  1. 从数列中挑出一个元素,称为 "基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。


代码:

int Partation(int a[], int low, int high)
{
	int val = a[low];
	
	while(low < high)
	{
		while( (low < high) && (a[high] >= val) )
		{
			--high;
		}
		a[low] = a[high];
		
		while( (low < high) && (a[low] <= val) )
		{
			++low;
		}
		a[high] = a[low];
	}
	a[low] = val;
	
	return low;
}

void QuickSort(int a[], int low, int high) //O(n * n)
{
	int pos = 0;
	
	if(low < high)
	{
		pos = Partation(a, low, high);
		QuickSort(a, low, pos-1);
		QuickSort(a, pos+1, high);
	}
}


感想:排序算法很精巧,真佩服当初能想出那种算法的计算机界大牛,自己还差很远。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:272354次
    • 积分:6445
    • 等级:
    • 排名:第3730名
    • 原创:123篇
    • 转载:21篇
    • 译文:0篇
    • 评论:79条
    博客简介
    **************************************
    欢迎大家一起交流、探索,共同进步!

    原创文章,转载请注明出处!

    交流qq群: 96595755
    交流范围:嵌入式、Linux、图像处理等。
    **************************************