排序概述
-
排序是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列。
-
数据元素: 数据的基本单位。在计算机中通常作为一个整体进行考虑。一个数据元素可由若干数据项组成。
-
关键字: 数据元素中某个数据项的值,用它可以标识(识别)一个数据元素。
-
在排序过程中需要完成的两种基本操作
-
比较两个数的大小
-
调整元素在序列中的位置
-
内部排序与外部排序
-
内部排序:待排序的数据元素存放在计算机内存中进行的排序过程。
-
外部排序:待排序的数据元素数量很大,以致内存存中一次不能容纳全部数据,在排序过程中尚需对外存进行访问的排序过程。
几种简单的内部排序方法
-
插入排序
每一步将一个待排序元素按其关键字值的大小插入到已排序序列的适当位置上,直到待排序元素插入完为止。 -
例 9-11 直接插入排序函数模板 template <class T> void insertionSort(T a[], int n) { int i, j; T temp; for (int i = 1; i < n; i++) { int j = i; T temp = a[i]; while (j > 0 && temp < a[j - 1]) { a[j] = a[j - 1]; j--; } a[j] = temp; } }
-
选择排序
选择排序的基本思想每次从待排序序列中选择一个关键字最小的元素,(当需要按关键字升序排列时),顺序排在已排序序列的最后,直至全部排完 -
template <class T> void mySwap(T &x, T &y) { T temp = x; x = y; y = temp; } template <class T> void selectionSort(T a[], int n) { for (int i = 0; i < n - 1; i++) { int leastIndex = i; for (int j = i + 1; j < n; j++) if (a[j] < a[leastIndex]) leastIndex = j; mySwap(a[i], a[leastIndex]); } }
-
交换排序
两两比较待排序序列中的元素,并交换不满足顺序要求的各对元素,直到全部满足顺序要求为止。最简单的交换排序方法——起泡排序(最多进行n-1趟)
起泡排序举例:对整数序列 8 5 2 4 3 按升序排序
例 9-13 起泡排序函数模板
template <class T>
void mySwap(T &x, T &y) {
T temp = x;
x = y;
y = temp;
}
template <class T>
void bubbleSort(T a[], int n) {
int i = n – 1;
while (i > 0) {
int lastExchangeIndex = 0;
for (int j = 0; j < i; j++)
if (a[j + 1] < a[j]) {
mySwap(a[j], a[j + 1]);
lastExchangeIndex = j;
}
i = lastExchangeIndex;
}
}
对具有n个元素的序列按升序进行起泡排序的步骤:
-
首先将第一个元素与第二个元素进行比较,若为逆序,则将两元素交换。然后比较第二、第三个元素,依次类推,直到第n-1和第n个元素进行了比较和交换。此过程称为第一趟起泡排序。经过第一趟,最大的元素便被交换到第n个位置。
-
对前n-1个元素进行第二趟起泡排序,将其中最大元素交换到第n-1个位置。
-
如此继续,直到某一趟排序未发生任何交换时,排序完毕。对n个元素的序列,起泡排序最多需要进行n-1趟。
查找
顺序查找
-
顺序查找的基本思想:
从序列的首元素开始,逐个元素与待查找的关键字进行比较,直到找到相等的。若整个序列中没有与待查找关键字相等的元素,就是查找不成功。
例9-14顺序查找函数模板
template <class T>
int seqSearch(const T list[], int n, const T &key) {
for(int i = 0; i < n; i++)
if (list[i] == key)
return i;
return -1;
}
折半查找(二分法查找)算法
-
对于已按关键字排序的序列,经过一次比较,可将序列分割成两部分,然后只在有可能包含待查元素的一部分中继续查找,并根据试探结果继续分割,逐步缩小查找范围,直至找到或找不到为止。
折半查找算法示例
用折半查找法,在下列序列中查找值为21的元素:
用折半查找法,在下列序列中查找值为20的元素: