1. 插入排序:每一趟将一个待排序的记录,按其关键字值得大小插入到已经排序的部分文件中的适当的位置上,直到插入完成
1.1 直接插入查询
基本思想:依次将每个记录插入到一个有序的序列中区。
#include <stdio.h>
#define MaxSize 100
typedef int KeyType; /*关键字类型*/
typedef char ElemType[10]; /*其他数据项类型*/
typedef struct
{
KeyType key; /*关键字域*/
ElemType data; /*其他数据域*/
} LineList; /*线性表元素类型*/
void InsertSort(LineList R[],int n)
{
int i,j;
LineList tmp;
for (i=1;i<n;i++)
{
tmp=R[i];
j=i-1;
while (j>=0 && tmp.key<R[j].key)/*元素后移,以便腾出一个位置插入tmp*/
{
R[j+1]=R[j];
j--;
}
R[j+1]=tmp; /*在j+1位置处插入tmp*/
}
}
void main()
{
LineList R[MaxSize];
KeyType a[]={75,87,68,92,88,61,77,96,80,72};
int n=10,i;
for (i=0;i<n;i++)
R[i].key=a[i];
printf("排序前:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
InsertSort(R,n);
printf("排序后:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
}
1.2 希尔排序
基本思想:把记录下标的一定增量d分组,对每组记录采用直接插入排序方法进行排序,随着增量的逐渐减小,所分成的组包含的记录越来越多,到增量为1时,整个数据合成为一组,构成一组有序记录,则完成排序。
#include <stdio.h>
#define MaxSize 100
typedef int KeyType; /*关键字类型*/
typedef char ElemType[10]; /*其他数据项类型*/
typedef struct
{
KeyType key; /*关键字域*/
ElemType data; /*其他数据域*/
} LineList; /*线性表元素类型*/
void ShellSort(LineList R[],int n)
{
int i,j,gap;
LineList tmp;
gap=n/2; /*增量置初值*/
while (gap>0)
{
for (i=gap;i<n;i++) /*对所有相隔gap位置的所有元素组进行排序*/
{
tmp=R[i];
j=i-gap;
while (j>=0 && tmp.key<R[j].key)/*对相隔gap位置的元素组进行排序*/
{
R[j+gap]=R[j];
j=j-gap; /*移到本组中的前一个元素*/
}
R[j+gap]=tmp;
j=j-gap;
}
gap=gap/2; /*减小增量*/
}
}
void main()
{
LineList R[MaxSize];
KeyType a[]={75,87,68,92,88,61,77,96,80,72};
int n=10,i;
for (i=0;i<n;i++)
R[i].key=a[i];
printf("排序前:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
ShellSort(R,n);
printf("排序后:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
}
2. 选择排序:每步从待排序的记录中选出关键字最小的记录,顺序放在已经排序的记录序列的最后,直到全部排完为止
2.1 直接选择排序
基本思想:每一趟排序在n-i-1(i=1,2,...,n-1)个记录中选取关键字最小的记录,并和第i个记录进行比较。
#include <stdio.h>
#define MaxSize 100
typedef int KeyType; /*关键字类型*/
typedef char ElemType[10]; /*其他数据项类型*/
typedef struct
{
KeyType key; /*关键字域*/
ElemType data; /*其他数据域*/
} LineList; /*线性表元素类型*/
void SelectSort(LineList R[],int n)
{
int i,j,k;
LineList tmp;
for (i=0;i<n-1;i++)
{
k=i;
for (j=i+1;j<n;j++)
if (R[j].key<R[k].key)
k=j; /*用k指出每趟在无序区段的最小元素*/
tmp=R[i]; /*将R[k]与R[i]交换*/
R[i]=R[k];
R[k]=tmp;
}
}
void main()
{
LineList R[MaxSize];
KeyType a[]={75,87,68,92,88,61,77,96,80,72};
int n=10,i;
for (i=0;i<n;i++)
R[i].key=a[i];
printf("排序前:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
SelectSort(R,n);
printf("排序后:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
}
2.2 堆排序
基本思想:堆是一个顺序存储的完全二叉树。首先,按堆得定义将R[i..n]调整为堆(这个过程叫做初始建堆),交换R[1]和R[n];然后,将R[1..n-1]调整为堆,交换R[1]和R[n-1];如此反复进行,直到交换了R[1]和R[2]为止。
#include <stdio.h>
#define MaxSize 100
typedef int KeyType; /*关键字类型*/
typedef char ElemType[10]; /*其他数据项类型*/
typedef struct
{
KeyType key; /*关键字域*/
ElemType data; /*其他数据域*/
} LineList; /*线性表元素类型*/
void Sift(LineList R[],int low,int high)
{
int i=low,j=2*i; /*R[j]是R[i]的左孩子*/
LineList tmp=R[i];
while (j<=high)
{ if (j<high && R[j].key<R[j+1].key) /*若右孩子较大,把j指向右孩子*/
j++; /*j变为2i+1,指向右孩子结点*/
if (tmp.key<R[j].key)
{ R[i]=R[j]; /*将R[j]调整到双亲结点位置上*/
i=j; /*修改i和j值,以便继续向下筛选*/
j=2*i;
}
else break; /*筛选结束*/
}
R[i]=tmp; /*被筛选结点的值放入最终位置*/
}
void HeapSort(LineList R[],int n)
{
int i;
LineList tmp;
for (i=n/2;i>=1;i--) /*循环建立初始堆*/
Sift(R,i,n);
for (i=n;i>=2;i--) /*进行n-1次循环,完成堆排序*/
{ tmp=R[1]; /*将第一个元素同当前区间内R[1]对换*/
R[1]=R[i];
R[i]=tmp;
Sift(R,1,i-1); /*筛选R[1]结点,得到i-1个结点的堆*/
}
}
void main()
{
LineList R[MaxSize];
KeyType a[]={0,75,87,68,92,88,61,77,96,80,72}; /*有效数据从a[1]开始*/
int n=10,i;
for (i=0;i<=n;i++)
R[i].key=a[i];
printf("排序前:");
for (i=1;i<=n;i++)
printf("%3d",R[i].key);
printf("\n");
HeapSort(R,n);
printf("排序后:");
for (i=1;i<=n;i++)
printf("%3d",R[i].key);
printf("\n");
}
3. 交换排序:两两比较待排序记录的关键字,并交换不满足次序要求的那些偶对,知道全部满足为止
3.1 冒泡排序
基本思想:通过无序区中相邻记录关键字间的比较和位置交换,使关键字最小的记录如气泡一般逐渐往上漂浮直至水面。
#include <stdio.h>
#define MaxSize 100
typedef int KeyType; /*关键字类型*/
typedef char ElemType[10]; /*其他数据项类型*/
typedef struct
{
KeyType key; /*关键字域*/
ElemType data; /*其他数据域*/
} LineList; /*线性表元素类型*/
void BubbleSort(LineList R[],int n)
{
int i,j,exchange;
LineList tmp;
for (i=0;i<n-1;i++)
{ exchange=0;
for (j=n-1;j>i;j--) /*比较,找出最小关键字的记录*/
if (R[j].key<R[j-1].key)
{ tmp=R[j]; /*R[j]与R[j-1]进行交换,将最小关键字记录前移*/
R[j]=R[j-1];
R[j-1]=tmp;
exchange=1;
}
if (exchange==0) /*本趟未发生交换时结束算法*/
return;
}
}
void main()
{
LineList R[MaxSize];
KeyType a[]={75,87,68,92,88,61,77,96,80,72};
int n=10,i;
for (i=0;i<n;i++)
R[i].key=a[i];
printf("排序前:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
BubbleSort(R,n);
printf("排序后:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
}
3.2 快速排序
基本思想:在待排序的n个记录中任取一个记录(通常取第一个记录),把该记录放入最终的位置后,整个数据区间被此分割成两个子区间。所有关键字比该记录关键字小的放置在前子区间中,所有比它大的放置在后子区间中,并把该记录排在这两个子区间的中间,这个过程称作一趟快速排序。之后对所有的两个子区间分别重复上述过程,直至每个子区间内只有一个记录为止。简而言之,每趟排序使表中的第一个元素入终位,将数据区间一分为二,对于子区间按递归方式继续这种划分,直至划分的子区间长为1.
#include <stdio.h>
#define MaxSize 100
typedef int KeyType; /*关键字类型*/
typedef char ElemType[10]; /*其他数据项类型*/
typedef struct
{
KeyType key; /*关键字域*/
ElemType data; /*其他数据域*/
} LineList; /*线性表元素类型*/
void QuickSort(LineList R[],int s,int t) /*对R[s]至R[t]的元素进行快速排序*/
{
int i=s,j=t;
LineList tmp;
if (s<t) /*区间内至少存在一个元素的情况*/
{ tmp=R[s]; /*用区间的第1个记录作为基准*/
while (i!=j) /*从区间两端交替向中间扫描,直至i=j为止*/
{ while (j>i && R[j].key>tmp.key)
j--; /*从右向左扫描,找第1个关键字小于tmp.key的R[j]*/
R[i]=R[j]; /*找到这样的R[j],则R[i]和R[j]交换*/
while (i<j && R[i].key<tmp.key)
i++; /*从左向右扫描,找第1个关键字大于tmp.key的R[i]*/
R[j]=R[i]; /*找到这样的R[i],则R[i]和R[j]交换*/
}
R[i]=tmp;
QuickSort(R,s,i-1); /*对左区间递归排序*/
QuickSort(R,i+1,t); /*对右区间递归排序*/
}
}
void main()
{
LineList R[MaxSize];
KeyType a[]={75,87,68,92,88,61,77,96,80,72};
int n=10,i;
for (i=0;i<n;i++)
R[i].key=a[i];
printf("排序前:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
QuickSort(R,0,n-1);
printf("排序后:");
for (i=0;i<n;i++)
printf("%3d",R[i].key);
printf("\n");
}