一,冒泡法
(按从小到大排序举例)
原理:通俗的讲,就是一遍一遍地,不断地把较大的数往下沉。
途径:交换两个数的位置。
举例:
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) | |||||
1 | 5 | 8 | 6 | 2 | 4 |
1 | 5 | 5 | 8 | 2 | 4 |
1 | 5 | tmp | 8 | 2 | 4 |
如上表格,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的地方),插入,完成排序。
}
}
}
三、快速排序
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;
}