(一)内部排序
所有的记录都能存放在内存中进行排序,称为内部排序;
对内部排序地而言,其基本操作有两种:
◆ 比较两个关键字的大小;<必不可少>
◆ 存储位置的移动:从一个位置移到另一个位置。<不一定:链式存储>
【1】插入排序
2-路插入排序
2-路插入排序是对折半插入排序的改进,以减少排序过程中移动记录的次数。附加n个记录的辅助空间,方法是:
① 另设一个和L->R同类型的数组d,L->R[1]赋给d[1],将d[1]看成是排好序的序列中中间位置的记录;
② 分别将L->R[ ]中的第i个记录依次插入到d[1]之前或之后的有序序列中,具体方法:
◆ L->R[i].key<d[1].key: L->R[i]插入到d[1]之前的有序表中;
◆ L->R[i].key≥d[1].key: L->R[i]插入到d[1]之后的有序表中
在2-路插入排序中,移动记录的次数约为n^2/8 。但当L->R1是待排序记录中关键字最大或最小的记录时,2-路插入排序就完全失去了优越性。
希尔排序(Shell Sort,又称缩小增量法)
希尔排序是一种分组插入排序方法。
排序思想:
① 先取一个正整数d1(d1<n)作为第一个增量,将全部n个记录分成d1组,把所有相隔d1的记录放在一组中,即对于每个k(k=1, 2, … d1),R[k], R[d1+k], R[2d1+k] , …分在同一组中,在各组内进行直接插入排序。这样一次分组和排序过程称为一趟希尔排序;
② 取新的增量d2 < d1,重复①的分组和排序操作;直至所取的增量di=1为止,即所有记录放进一个组中排序为止。
/***************************************************
* shell sort
****************************************************/
//参数n为数组大小,d为增量
void shell_pass(int a[], int n, int d){
int guard, i, j, k;
for (k = 0; k < d; k++)/*共有d组*/ {
for (i = k+d; i < n; i+=d){
guard = a[i];
for (j = i - d; j >= 0; j-=d) {
if (guard < a[j]) a[j + d] = a[j];
else break;
}
a[j + d] = guard;
}
}
}
//增量选取初始为数组大小一半。
void shell_sort(int a[], int n){
int d = n / 2;
while (d >= 1) {
shell_pass(a, n, d);
d /= 2;
}
}
【2】快速排序
排序思想:
通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对这两部分记录进行下一趟排序,以达到整个序列有序。
一趟快速排序方法:
从序列的两端交替扫描各个记录,将关键字小于基准关键字的记录依次放置到序列的前边;而将关键字大于基准关键字的记录从序列的最后端起,依次放置到序列的后边,直到扫描完所有的记录。该关键字称它为“枢纽值”【枢纽值选取方法有很多,这里选序列第一个元素作为枢纽值】