包括插入排序、希尔排序、堆排序、归并排序及快速排序
1、插入排序
插入排序利用了这样的事实:若插入位置为P,则位置0到位置P-1上的元素已排过序。每次插入前P+1个元素的正确位置。
void InsertionSort(ElementType a[], int N)
{
ElementType tmp;
int p, j;
for (p = 1; p < N; p++)
{
tmp = a[p];
for (j = p; j>0 & a[j - 1] > tmp; j--)
a[j] = a[j - 1];
a[j] = tmp;
}
}
2、希尔排序
希尔排序是通过比较相距一段间隔的元素来工作,各趟比较所用的距离随着算法的进行而减少,直到只比较相邻元素的最后一趟排序为止。因此,有时也叫缩小增量排序(diminishing increment sort)。
void shellSort(ElementType a[], int N)
{
ElementType tmp;
int Increment, i, j;
for (Increment = N / 2; Increment > 0; Increment /= 2)
{
for (i = Increment; i < N; i++)
{
tmp = a[i];
for (j = i; j >= Increment; j -= Increment)
{
if (a[j - Increment]>tmp)
a[j] = a[j - Increment];
else
break;
}
a[j] = tmp;
}
}
}
不同增量序列:
(1)Hibbard增量:1,3,7,...,2^k-1
//****************希尔排序(Hibbard增量)****************//
int log2(int n)
{
return int(log(double(n)) / log(double(2)));
}
void shellSort1(ElementType a[], int N)
{
int Kt = log2(N);
int k, Increment, i, j;
ElementType tmp;
for (k = Kt; k > 0; k--)
{
Increment = int(pow(2.0, k) - 1);
for (i = Increment; i < N; i++)
{
tmp = a[i];
for (j = i; j >= Increment; j -= Increment)
{
if (a[j - Increment]>tmp)
a[j] = a[j - Increment];
else
break;
}
a[j] = tmp;
}
}
}
(2)Sedgewick增量:9*4^i-9*2^i+1
//*****************希尔排序(Sedgewick增量)***************//
int log4(int n)
{
return int(log(double(n)) / log(double(4)));
}
void shellSort2(ElementType a[], int N)
{
int Kt = log4((N-1)/9);
int k, Increment, i, j;
ElementType tmp;
for (k = Kt; k >=0; k--)
{
Increment = int(9*pow(4.0, k)-9*pow(2.0,k) + 1);
for (i = Increment; i < N; i++)
{
tmp = a[i];
for (j = i; j >= Increment; j -= Increment)
{
if (a[j - Increment]>tmp)
a[j] = a[j - Increment];
else
break;
}
a[j] = tmp;
}
}
}
3、堆排序
最大堆的父节点大于等于任意一个孩子节点,所以每次可以取出根节点进行排序,为了不使用附加的数组,可以将根节点与最后一个元素交换,然后下滤来保持堆性质,依次类推,最后得到一个从小到大的序列。
#define LeftChild(i) (2*(i)+1)//数组是从0开始的
//***************堆排序********************************//
void PercDown(ElementType a[], int i, int N)
{
int child;
ElementType tmp;
for (tmp = a[i]; LeftChild(i) < N; i = child)
{
child = LeftChild(i);
if (child != N - 1&&a[child+1]>a[child])
child++;
if (tmp < a[child])
a[i] = a[child];
else
break;
}
a[i] = tmp;
}
void Heapsort(ElementType a[], int N)
{
int i;
for (i = N / 2; i >= 0; i--)
PercDown(a, i, N);
for (i = N - 1; i > 0; i--)
{
swap(a[0], a[i]);
PercDown(a, 0, i);
}
}
4、归并排序
对两个已经排好序的子序列排序。
void Merge(ElementType a[], ElementType TmpArray[], int Lpos, int Rpos, int RightEnd)
{
int i, LeftEnd, TmpPos, NumElements;
LeftEnd = Rpos - 1;
TmpPos = Lpos;
NumElements = RightEnd - Lpos + 1;
while (Lpos <= LeftEnd&&Rpos <= RightEnd)
{
if (a[Lpos] <= a[Rpos])
TmpArray[TmpPos++] = a[Lpos++];
else
TmpArray[TmpPos++] = a[Rpos++];
}
while (Lpos <= LeftEnd)
TmpArray[TmpPos++] = a[Lpos++];
while (Rpos <= RightEnd)
TmpArray[TmpPos++] = a[Rpos++];
for (i = 0; i < NumElements; i++, RightEnd--)
{
a[RightEnd] = TmpArray[RightEnd];
}
}
void MSort(ElementType a[], ElementType TmpArray[], int left, int right)
{
int center;
if (left < right)
{
center = (left + right) / 2;
MSort(a, TmpArray, left, center);
MSort(a, TmpArray, center + 1, right);
Merge(a, TmpArray, left, center + 1, right);
}
}
void Mergesort(ElementType a[], int N)
{
ElementType *TmpArray;
TmpArray =(ElementType *)malloc(N*sizeof(ElementType));
if (TmpArray != NULL)
{
MSort(a, TmpArray, 0, N - 1);
free(TmpArray);//free出错,可能是数组越界
}
else
printf("No space for array!!!");
}
5、快速排序
快速排序与归并排序一样也是一种递归的分治方法,选取一个pivot,将小于或等于pivot的放在左边,将大于或等于pivot的放在右边。
//******************快速排序*********************************//
ElementType Median3(ElementType a[], int left, int right)
{
int center = (left + right) / 2;
if (a[left] > a[center])
swap(a[left], a[center]);
if (a[left] > a[right])
swap(a[left], a[right]);
if (a[center] > a[right])
swap(a[center], a[right]);
swap(a[center], a[right - 1]);
return a[right - 1];
}
void Qsort(ElementType a[], int left,int right)
{
int i, j;
ElementType pivot;
if (left + cutoff <= right)
{
pivot = Median3(a, left, right);
i = left;
j = right - 1;
for (;;)
{
while (a[++i] < pivot){}
while (a[--j]>pivot){}
if (i < j)
swap(a[i], a[j]);
else
break;
}
swap(a[i], a[right - 1]);
Qsort(a, left, i - 1);
Qsort(a, i + 1, right);
}
else
{
InsertionSort(a + left, right - left + 1);
}
}
void QuickSirt(ElementType a[], int N)
{
Qsort(a, 0, N - 1);
}
快速查找**************************************//
void Qselect(ElementType a[], int k, int left, int right)
{
int i, j;
ElementType pivot;
if (left + cutoff <= right)
{
pivot = Median3(a, left, right);
i = left;
j = right - 1;
for (;;)
{
while (a[++i] < pivot){}
while (a[--j]>pivot){}
if (i < j)
swap(a[i], a[j]);
else
break;
}
swap(a[i], a[right - 1]);
if (k <= i)
Qselect(a, k, left, i - 1);
else if (k>i + 1)
Qselect(a, k, i + 1, right);
}
else
{
InsertionSort(a + left, right - left + 1);
}
}
ElementType QuickSelect(ElementType a[], int k,int N)
{
Qselect(a, k, 0, N - 1);
return a[k - 1];
}
用到的其他函数及主函数
#include "stdafx.h"
#include<time.h>
#include<math.h>
#include<stdlib.h>
#include<malloc.h>
#define M 10
#define LeftChild(i) (2*(i)+1)
#define cutoff 3
typedef int ElementType;
void randm(int a[]) //产生随机数
{
int i;
int b;
srand(time(NULL));
for (i = 0; i < M; i++)
{
b = rand();
a[i] = (b% 100);
}
}
void swap(ElementType &a, ElementType &b)//交换两个数
{
ElementType tmp;
tmp = a;
a = b;
b = tmp;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[M] = { 21,71,71,26,93,95,35,78,84,47 };
//randm(a);
for (int i = 0; i < M; i++)
printf("%d ", a[i]);
printf("\n");
QuickSirt(a, M);
for (int i = 0; i < M; i++)
printf("%d ", a[i]);
ElementType p;
p=QuickSelect(a, 5,10);
printf("\n%d\n", p);
return 0;
}