希尔排序
输入:表长length,以及表中各元素的值,类型为int。
输出:表内的值按由小至大输出。
优化目标:无
分析:1.不稳定排序;2.只能用于顺序结构,不能用于链式结构;3.增量序列可以有各种取法,但应该使增量序列中值没有除1之外的公因子,并且最后一个增量值必须等于1;4.记录总的比较次数和移动次数都比直接插入排序要少,n越大时,效果越明显。所以适用于初始记录无序、n较大时的情况。
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 20
typedef struct{
int key; //关键字
}KeyType;
typedef struct{
KeyType R[MAXSIZE+1]; //R[0]闲置
int length; //顺序表的长度
}SqList;
//单次希尔排序
void ShellInsert(SqList &L,int dk){
int i,j;
for(i = dk+1;i<=L.length;i++){
if(L.R[i].key<L.R[i-dk].key){
L.R[0] = L.R[i];
for(j = i-dk;j>0&&L.R[0].key<L.R[j].key;j-=dk){
L.R[j+dk] = L.R[j];
}
L.R[j+dk] = L.R[0];
}
}
}
//希尔排序
void ShellSort(SqList &L,int dt[],int t){
int k;
for(k = 0;k<t;k++){
ShellInsert(L,dt[k]);
}
}
//初始化列表
void ListInit(SqList &L){
int i,length,key;
for(i = 1;i<=MAXSIZE;i++){
L.R[i].key = 0;
}
printf("请输入顺序表的长度(小于20):");
scanf("%d",&length);
L.length = length;
for(i = 1;i<=length;i++){
printf("请输入第%d个元素:",i);
scanf("%d",&key);
L.R[i].key = key;
}
}
//输出列表
void PrintList(SqList L){
int i;
printf("排序结果是:");
for(i = 1;i<=L.length;i++){
printf("%d ",L.R[i].key);
}
}
int main(){
SqList L;
int dt[3] = {5,3,1};
ListInit(L);
ShellSort(L,dt,3);
PrintList(L);
return 0;
}
快速排序
输入:表长length,以及表中各元素的值,类型为int。
输出:表内的值按由小至大输出。
优化目标:无
分析:1.不稳定排序;2.排序过程中需要定位表的下界和上界,所以适合用于顺序结构,很难用于链式结构;3.当n较大时,在平均情况下快速排序是所有内部排序方法中速度最快的一种,所以其适合初始记录无序、n较大时的情况。
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 20
typedef struct{
int key; //关键字
}KeyType;
typedef struct{
KeyType R[MAXSIZE+1]; //R[0]闲置
int length; //顺序表的长度
}SqList;
//对顺序表中的子表R[low..high]进行一次排序,返回枢轴位置
int Partition(SqList &L,int low,int high){
L.R[0] = L.R[low];
int p = L.R[low].key;
while(low < high){
while(low < high && L.R[high].key>=p){
--high;
}
L.R[low] = L.R[high];
while(low < high && L.R[low].key<=p){
low++;
}
L.R[high] = L.R[low];
}
L.R[low] = L.R[0];
return low;
}
//对子表R[low..high]进行一次快速排序
void QSort(SqList &L,int low,int high){
if(low<high){
int p = Partition(L,low,high);
QSort(L,low,p-1);
QSort(L,p+1,high);
}
}
//对顺序表L进行快速排序
void QuickSort(SqList &L){
QSort(L,1,L.length);
}
//初始化列表
void ListInit(SqList &L){
int i,length,key;
for(i = 1;i<=MAXSIZE;i++){
L.R[i].key = 0;
}
printf("请输入顺序表的长度(小于20):");
scanf("%d",&length);
L.length = length;
for(i = 1;i<=length;i++){
printf("请输入第%d个元素:",i);
scanf("%d",&key);
L.R[i].key = key;
}
}
//输出列表
void PrintList(SqList L){
int i;
printf("排序结果是:");
for(i = 1;i<=L.length;i++){
printf("%d ",L.R[i].key);
}
}
int main(){
SqList L;
ListInit(L);
QuickSort(L);
PrintList(L);
return 0;
}
堆排序
输入:表长length,以及表中各元素的值,类型为int。
输出:表内的值按由小至大输出。
优化目标:无
分析:1.不稳定排序;2.只能用于顺序结构,不能用于链式结构;3.初始建堆所需要的比较次数较多,因此记录数较少时不宜采用。
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 20
typedef struct{
int key; //关键字
}KeyType;
typedef struct{
KeyType R[MAXSIZE+1]; //R[0]闲置
int length; //顺序表的长度
}SqList;
//将R[s..m]调整为以R[s]为根的大根堆
void HeapAdjust(SqList &L,int s,int m){
KeyType rc = L.R[s];
int j;
for(j = 2*s;j<=m;j = j*2){
if(j<m && L.R[j].key<L.R[j+1].key){
j++;
}
if(rc.key>=L.R[j].key){
break;
}
L.R[s] = L.R[j];
s = j;
}
L.R[s] = rc;
}
//把无序序列建成大根堆
void CreatHeap(SqList &L){
int n = L.length;
int i;
for(i = n/2;i>0;i--){
HeapAdjust(L,i,n);
}
}
//堆排序
void HeapSort(SqList &L){
CreatHeap(L);
int i;
for(i=L.length;i>1;i--){
KeyType x = L.R[i];
L.R[1] = L.R[i];
L.R[i] = x;
HeapAdjust(L,1,i-1);
}
}
//初始化列表
void ListInit(SqList &L){
int i,length,key;
for(i = 1;i<=MAXSIZE;i++){
L.R[i].key = 0;
}
printf("请输入顺序表的长度(小于20):");
scanf("%d",&length);
L.length = length;
for(i = 1;i<=length;i++){
printf("请输入第%d个元素:",i);
scanf("%d",&key);
L.R[i].key = key;
}
}
//输出列表
void PrintList(SqList L){
int i;
printf("排序结果是:");
for(i = 1;i<=L.length;i++){
printf("%d ",L.R[i].key);
}
}
int main(){
SqList L;
ListInit(L);
HeapSort(L);
PrintList(L);
return 0;
}
今天主要复习了一下比较复杂的排序方法(希尔排序、快速排序、堆排序),排序方法很多,每一种方法都有各自的优缺点,适合在不同的环境下使用。当待排序列的记录个数n较小时,可以选用简单的排序;当n较大时,应选用先进的排序方法。明天打算针对线性表的题目进行练习,然后还要对前面的知识再复习。