排序的相关概念
排序的分类
-
根据在排序过程中带排序的记录是否全部被放置在内存中,排序分为:
-
内排序
-
外排序
-
1.内排序
内排序是在排序整个过程中,带排序的所有记录全部放置在内存中。
影响内排序的主要因素
-
时间性能。
-
-
(主要受比较和移动两种操作的影响)
-
-
辅助空间。
-
算法的复杂性。
内排序的分类
根据排序过程中借助的主要操作,内排序分为:
-
插入排序
-
交换排序
-
选择排序
-
归并排序
2.外排序
外排序是由于排序的记录个数太多,不能同时放置在内存中,整个排序过程需要在内外存之间多次交换数据才能进行。
按照算法的复杂度分类
-
简单算法:
-
-
冒泡排序、简单选择排序、直接插入排序。
-
-
复杂排序:
-
希尔排序、堆排序、归并排序、快速排序。
-
一、冒泡排序算法
因为在冒泡排序中要用到顺序表结构和数组两元素的交换,先把这些写成函数
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
#define TRUE 1
#define FALSE 0
typedef struct {
int r[MAXSIZE + 1];
int length;
}SqList;
void swap(SqList *L, int i, int j){
int temp = L->r[i];
L->r[i] = L->r[j];
L->r[j] = temp;
}
1.1 冒泡排序的初级版实现
冒泡排序(Bubble Sort)是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。
void BubblSort0(SqList *L){
int i,j;
for (i = 1; i < L->length; i++)
for (j = i+1; j <= L->length; j++)
if (L->r[i] > L->r[j])
swap(L, i, j);
}
对于这段代码,是最简单的冒泡,其实就是最简单的交换排序而已。它的思路就是让每一个关键字,都和它后面的每一个关键字比较,如果大则交换,这样第一位置的关键字在第一次循环后一定变成最小值。
假设我们待排序的关键字序列是{9,1,5,8,3,7,4,6,2}
-
当
i = 1
时,9与1交换后,在第一位置的1与后面的关键字比较都小,因此它就只最小值。 -
当
i = 2
时,第二位置先后由9换成5,换成3,换成2,完成了第二小的数字交换。 -
后面数字依次比较和交换,得到最终结果。
1.2 冒泡排序的实现
对于上面的算法,代码虽然简单易懂,但是效率非常低。可以改进成接下来的代码
void BubbleSort(SqList *L){
int i,j;
for (i = 1; i < L->length; i++)
for (j = L->length - 1; j >= i; j--)
if (L->r[j] > L->r[j+1])
swap(L, j, j+1);
}
代码解释
假设我们待排序的关键字序列是{9,1,5,8,3,7,4,6,2}
-
当
i = 1
时,变量j由8反向循环到1,逐个比较,将较小值交换到前面,直到最后找到最小值放置在了第1的位置。 -
当
i = 1
、j = 8
时,6 > 2 ,因此交换了它们的位置,j = 7
时,4 > 2, 所以交换......直到j = 2
时,因为 1 < 2, 所以不交换。 -
j = 1 时,9 > 1,交换,最终得到最小值1放置第一的位置。
-
在不断循环的过程中,除了将关键字1放到第一的位置,还将关键字2从第九位置提到了第三的位置,显然比前面的算法有进步。
-
当
i = 2
时,变量j
由8反向循环到2,逐个比较,在将关键字2交换到第二位置的同时,也将关键字4和3有所提升。
1.3 冒泡排序的优化
-
在排序的过程中,增加一个标记变量flag来记录位置是否发生了变化
-
如果没有发生交换,说明数组已经有序了。
-
void BubbleSort1(SqList *L){ int i