快速排序的递归实现:
typedef int Item;
#define key(A) (A)
#define less(A, B) (key(A)< key(B))
#define exch(A, B) { Item t = A; A = B; B = t; }
#define compexch(A, B) if(less(B, A)) exch(A, B)
int partition(Item a[], int l, int r)
{
int i = l-1, j=r;
Item v = a[r];
for ( ; ; ) {
while (less(a[++i], v)) ;
while (less(v, a[--j]))
if (j == l)
break;
exch(a[i], a[j]);
}
exch(a[i], a[r]);
return i;
}
void quicksort(Item a[], int l, int r)
{
int i;
if (r<=l)
return;
i = partition(a, l, r);
quicksort(a,l, i-1);
quicksort(a,i+1, r);
}
非递归快速排序:
使用了一个显示的下推栈,通过向栈中压入参数和过程调用 不断的从栈中弹出参数来替代递归调用,这个过程走到栈为空。我们把两个子文件的较大者压入栈中来确保栈的最大深度为lgN。
#define push2(S, A, B) S.push(B); S.push(A);
void quicksort2(Item a[], int l, int r)
{
int i;
stack<int> s;
push2(s, l, r);
while (!s.empty()) {
l = s.top(); s.pop();
r = s.top(); s.pop();
i = partition(a, l, r);
if (i - 1 > r - i)
{
push2(s, l, i-1);
push2(s, i+1, r);
}
else
{
push2(s, i+1, r);
push2(s, l, i-1);
}
}
}
1 递归程序调用自身的许多小的子文件,忽略栈中找到的所有小于M的文件,这类文件使用插入排序来运行和直接将这些小文件合并差不多。
2 三者取中划分 不取最右边的元素作为划分值,而使用首元素,中间元素,尾元素的中间值作为划分元素,减少出现最坏情况的概率。
3 重复关键字的处理。把数组划分为三部分,比划分元素小的元素, 与划分元素相等的元素, 比划分元素大的元素。
重复关键字算法:
#define eq(A, B) (!less(A, B) && !(less(B, A)))
void quicksort3(Item a[], int l, int r)
{
int i, j, k, p, q;
Item v;
if (r <= l) {
return;
}
v = a[r];
i = i - 1; j = r; p = i - 1; q = r;
for (; ;) {
while (less(a[++i], v)) ;
while (less(v, a[--j])) if(j == l) break;
if (i>=j) break;
exch(a[i], a[j]);
if (eq(a[i], v)) {
p++;
exch(a[p], a[i]);
}
if (eq(v, a[j])) {
q--;
exch(a[q], a[j]);
}
}
exch(a[i], a[r]);
j = i - 1; i = i+1;
for (k = 1; k<p ; k++, j--) {
exch(a[k], a[j]);
}
for (k = r-1; k>q ; k--, i++) {
exch(a[k], a[i]);
}
quicksort(a, l, j);
quicksort(a, i, r);
}
三种基本的排序:
选择排序算法:首先选出数组中最小的元素跟数组中第一个元素交换,然后找出次小的元素与数组中第二个元素交换。。。
void selection(Item a[], int l, int r)
{
int i, j;
for ( i = l; i<r; i++) {
int min = i;
for (j = i+1; j<r; j++)
if (less(a[j], a[min])) min = j;
exch(a[i], a[min]);
}
}
插入排入:为了插入新数据,先将较大的元素一个一个向右移动,然后将新数据插入到空位中。
void inserttion(Item a[], int l, int r)
{
int i;
// 找出最小元素作为观察哨
for (i = r; i>l; i--)
compexch(a[i-1], a[i]);
for (i = l+2; i<=r; i++) {
int j = i;
Item v = a[i];
while (less(v, a[j-1])) {
a[j] = a[j-1];
j--;
}
a[j] = v;
}
}
void bubble(Item a[], int l, int r)
{
int i, j;
for (i = l; i<r; i++) {
for (j = r; j>i; j--) {
compexch(a[j-1], a[j]);
}
}
}
步长序列是1 4 13 40 121 364 1093 的希尔算法:
void shellsort(Item a[], int l, int r)
{
int i, j, h;
// 先从最大的开始
for (h = l; h<=(r-1)/9; h=3*h+1) ;
for (; h>0; h/=3) {
for (i = l+h; i<=r; i++) {
j = i; Item v = a[i];
while (j>=l+h && less(v, a[j-h])) {
a[j] = a[j-h];
j -= h;
}
a[j] = v;
}
}
}