您的位置:首页 > 其它

冒泡+直接插入+ 快速排序

2014-09-23 18:33 531 查看

一,冒泡法

(按从小到大排序举例)

原理:通俗的讲,就是一遍一遍地,不断地把较大的数往下沉。

途径:交换两个数的位置。

举例:

7
2
5
8
3
第一遍,把a[0] 与 a[1]比较,7 > 2, so, swap.

then, a[1] , a[2] 比较, 7 > 5 , 再交换。

……

第一遍结果是 8 存到了最下边。

伪代码细节: 若数组有n = 5,个元素,第一遍相邻两两之间要比较n - 1 次 才能把最大的数 沉到
最下边。

最大的数沉到最下边之后,就不用再管该数了。

第二遍时,比较前4个数,这4个数相邻两两之间比较,要比较3 次,才能把次大的数 填充 在倒数第二个框中。

遍历 次数的问题: 每遍历一次,确定一个元素的位置;当遍历4次时,就剩下最顶端的一个元素;一个元素就不相邻之间 相互比较了。

所以,需要遍历 n - 1 遍。

for i = 0;  i < n -1 ; i ++   //  遍历 n-1遍
     				for j=0;j < n - i -1 ; j++ //第一遍比较n-1次,第二遍比较n-2次 。


代码实现:

void bubble_sort(int *a, int n)
{
int itmp = 0;
int i = 0,j=0;
for(i = 0; i < n - 1; i++)//  遍历 n-1遍
{
    for(j = 0; j < n - i -1; j ++)  //第一遍比较n-1次,第二遍比较n-2次 。
    {
        if (a[j] > a[ j + 1 ])  //交换顺序,不断把大的沉入 底部。
        {
            itmp = a[j];
            a[j] = a[ j +1 ];
            a[ j + 1 ] = itmp;
        }
    }
}
}


至于空间复杂度等深层次理论东西,有待了解研究。

二、直接插入排序法

思想:假设一段序列,n 个元素, a[ 0 ] 到 a[ n - 1 ], 起初就默认a[ 0 ] 到a[ i -1 ]为已经排好序的 有序子序列,,现在要把a [ i ] 插入前边的 有序子序列里边。

(p.s 起初 i = 1, 所以 a[ 0 ]就为 有序子序列; 不断把 a[ i ] 插入有序子序列,知道 i == n -1)

途径:把a[ i ] 的值暂存给tmp(tmp = a[ i ]);不断地遍历,寻找 a[ i ] 应该插入 有序子序列中的位置;从插入点到 a[ i ],依次把数组后移(a[ i ] = a [ i -1 ]);

然后把tmp赋值给 插入点;完成一个元素插入有序子序列。

举例:

tmp=a[ i ] (==6)
158624
155824
15tmp824
如上表格,1,5,8,是有序子序列, 6 是待排序的元素 a [ i ], 因为 a [ i ] < a [ i - 1 ],所以要把 a [ i ] 插入到前面的有序子序列中;

暂存 a [ i ]给 tmp,然后 有序子序列 向后覆盖的过程中顺便寻找 tmp应该在 有序子序列 中的位置;然后把tmp赋值为相应的位置。

代码实现:

void dire_insert_sort(int *a, int n)
{
int i = 0, j = 0, tmp = 0;
for( i = 1; i < n; i ++) //i从一开始,起初把a[ 0]作为有序子序列。
{
     if ( a[ i] < a[ i - 1 ])  //若a[ i ](即 6) 比 有序子序列的最大的一个数(a[ i -1 ],即 8)还小,则 6 要插入 有序子序列,否则直接比较下一个
    {
             tmp = a[ i ];  //暂存要排序的元素,即 a[ i ]. 
             for( j = i - 1; (j >= 0) && (tmp < a[j]); j-- ) //寻找tmp要插入的地方,一旦 tmp大于 a[j],停止数组右移。
             {
                  a[ j + 1 ] = a[ j ];  // 寻找过程中,数组右移。
             }
            a[ j +1 ] = tmp;  // 找到应该插入的位置(上面表格中,第二个5的地方),插入,完成排序。
     }
}
}


三、快速排序

编辑时间:2015.9.9.14.35
1、采用 分治 的策略, 划分成 多个 子块,各个子块 再进行各自排序;
2、把首元素 作为标志数,把序列 按标志数 划分成 两个子序列, 左边 都是 小于标志数的, 右边是大于标志数的;
3、对前子序列 left…… i-1 回调, 对后子序列 i+1…… right 也进行回调。
4、程序2 也可以, 不知为什么,细节还未研究, 就是比较次数多一点,留待时间充足再追究 分析。
void quick_sort1(int s[], int left, int right)
{
	int i = 0, j = 0, tmp = 0, k = 0;

	if (left < right)
	{
		i = left;
		j = right;

		tmp = s[i];  /*暂存 序列 首元素 为 标志数, 以后以该数进行 左右序列划分*/

		while(i < j) /*此while 划分 以 i 为分界点,划分成两个子序列,左侧小于s[i], 右侧大于s[i]*/
		{
			while((i < j) && (s[j] > tmp)) j--;
			if (i < j) s[i++] = s[j];

			while((i < j) && (s[i] < tmp)) i++;
			if (i < j) s[j--] = s[i];
		}	

		s[i] = tmp;  /*把标志数 赋值到 标志位的地方(原s[i] 是一个 重复于 序列中的一个数 )*/ 
		quick_sort1(s, left, i-1);		
		quick_sort1(s, i+1, right);		
	}

	return;
}

void quick_sort2(int s[], int left, int right) /*似乎也可以, 但思想混乱, 需要细细研究*/
{
	int i = 0, j = 0, tmp = 0, k = 0;

	i = left;
	j = right;
	tmp = s[i];

	while(i < j)
	{
		while((i < j) && (s[j] > tmp)) j--;
		if (i < j) s[i++] = s[j];

		while((i < j) && (s[i] < tmp)) i++;
		if (i < j) s[j--] = s[i];

		s[i] = tmp;
		quick_sort2(s, left, i-1);		
		quick_sort2(s, i+1, right);		
	}

	return;
}




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐