## **内部排序**+外部排序**
```c
#include <stdio.h>
#include "stdlib.h"
#define KEYTYPE int
#define MAXSIZE 100
#define N 10
#define RADIX 10
typedef struct
{ KEYTYPE key;
}RcdType;
typedef struct {
RcdType r[MAXSIZE+1]; // r[0]闲置
int length; // 顺序表长度
int maxkey;
} SqList; // 顺序表类型
typedef struct{
int key;
int next;
}SLcell;
typedef struct{
SLcell *r;
int keynum;
int recnum;
}SLlist;
typedef int ArrType[RADIX];
void createList(SqList &L)
{
int k;
printf("\n>>>>>>>>>>系统将随机产生长度为%d的一张待排序的顺序表L<<<<<<<<<<\n\n",N);
k = 0;L.maxkey=0;
while(k<N)
{
k++;
L.r[k].key = rand()%1000;
if(L.r[k].key>L.maxkey)
L.maxkey=L.r[k].key;
}
L.length=k;
}
void print_SqList(SqList L)
{int i;
for (i = 0; i < L.length; i++)
printf(" %d",L.r[i+1].key);
printf("\n");
}
void insertsort(SqList &L)
{/*直接插入排序*/
int i,j;
for(i = 2; i <= L.length; i++)
{ L.r[0] = L.r[i]; j = i - 1; /*r[0]是监视哨,j表示当前已排好序列的长度*/
while(L.r[0].key < L.r[j].key) /*确定插入位置*/
{L.r[j + 1] = L.r[j]; j--;}
L.r[j + 1] = L.r[0]; /*元素插入*/
}
}
void insertsort_bin(SqList&L)
{/*折半插入排序*/
int i,j,low,high,mid;
for(i = 2; i <= L.length; i++)
{
if(L.r[i].key<L.r[i-1].key)
{
L.r[0]=L.r[i];
low=1;high=i-1;
while(low<=high)
{
mid=(low+high)/2;
if(L.r[mid].key<L.r[0].key)
low=mid+1;
else
high=mid-1;
}
for(j=i;j>high+1;j--)
L.r[j]=L.r[j-1];
L.r[high+1]=L.r[0];
}
}
}
void ShellInsert(SqList&L,int dk)
{/*对顺序表L做一趟希尔插入排序,前后记录的增量是dk,而不是1 ,0号单元只是暂存单元,不是哨兵。当j<=0时,插入位置已找到*/
int i,j;
for(i=dk+1;i<=L.length;i++)
if(L.r[i].key<L.r[i-dk].key)//"<",需将L.r[i]插入有序子表
{L.r[0]=L.r[i];//暂存在0号单元
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 dlta[],int t)
{//按增量序列dlta[0..t-1]对顺序表L作希尔排序
for(int k=0;k<t;++k)
ShellInsert(L,dlta[k]);//一趟增量为dlta[k]的插入排序
}
void bublesort(SqList &L)
{/*简单交换排序:冒泡排序*/
int i, j,swapflag=1;
RcdType temp;
for(i = 1; i < L.length&&swapflag; i++)
{
swapflag=0;
for(j = L.length - 1; j >= i; j--)
if(L.r[j + 1].key < L.r[j].key)
{temp = L.r[j + 1];
L.r[j + 1] = L.r[j];
L.r[j] = temp;
swapflag=1;}
}
}
int partition(SqList &L, int low, int high)
{/*一趟快速排序,返回i,产生了两个独立的待排子序列*/
int i, j;
RcdType temp;
i = low; j = high;
temp = L.r[i]; /*枢轴记录保存在temp变量中*/
do{ while((L.r[j].key >= temp.key) && (i < j)) j--; /*j指针记录和枢轴记录比较*/
if(i < j) { L.r[i] = L.r[j]; i++;}
while((L.r[i].key <= temp.key) && (i < j)) i++; /*i指针记录和枢轴记录比较*/
if(i < j) { L.r[j] = L.r[i]; j--;}
}while(i != j);
L.r[i] = temp; /*枢轴记录的排序位置确定在i*/
return i;
}
void quicksort(SqList &L ,int start, int end)
{/*快速排序*/
int i;
if(start < end)
{ i = partition(L, start, end); /*一趟快速排序,返回i,产生了两个独立的待排子序列*/
quicksort(L, start, i - 1); /*对两个独立的待排子序列分别递归调用快速排序算法*/
quicksort(L, i + 1,end);}
}
void selectsort(SqList &L)
{/*简单选择排序*/
int i,j,k;
RcdType temp;
for(i = 1; i < L.length; i++)
{ k = i; /*k:最小关键字的初始位置*/
for(j = i + 1; j <= L.length; j++)
if(L.r[j].key < L.r[k].key)
k = j; /*k:跟踪记录当前最小关键字的位置*/
if(k != i) /*最小关键字元素和待排序列的第一个元素交换*/
{temp = L.r[i]; L.r[i] = L.r[k]; L.r[k] = temp;}
}
}
void sift(SqList &L, int i, int m)
{/*i是根结点编号,m是以i结点为根的子树中最后一个结点的编号*/
int j;
RcdType temp;
temp = L.r[i];
j = 2 * i; /*j为i根结点的左孩子*/
while(j <= m)
{if(j < m && (L.r[j].key < L.r[j + 1].key))
j++; /*当i结点有左右孩子时,j取关键字大的孩子结点编号*/
if(temp.key < L.r[j].key)
{ L.r[i] = L.r[j]; i = j; j = 2 * i;}/*按堆定义调整,并向下一层筛选调整 */
else break; /*筛选调整完成,跳出循环 */
}
L.r[i] = temp;
}
void heapsort(SqList &L)
{/*堆排序: n为r表中记录数,从r[1]开始放起*/
int i;
RcdType temp;
for(i = L.length/2; i >= 1; i--)
sift(L, i, L.length); /*将无序序列建成大堆*/
for(i = L.length; i >= 2; i--)
{temp = L.r[1]; /*堆顶及堆尾元素交换*/
L.r[1] = L.r[i];
L.r[i] = temp;
sift(L,1,i - 1); /*交换后,从第一个元素开始调整为大堆,每次记录个数少一个*/
}
}
void merge(RcdType SR[], RcdType TR[], int low, int high ,int mid)
{
int i = low;
int k = low;
int j = mid + 1;
while ( i<= mid&&j<= high)
{
if (SR[i].key<SR[j].key)
TR[k++] = SR[i++];
else
TR[k++] = SR[j++];
}
while (i <= mid)
TR[k++] = SR[i++];
while (j <= high)
TR[k++] = SR[j++];
}
void MSort(RcdType SR[], RcdType TR[] ,int low, int high, int max_size)
{
if (low == high)
TR[low] = SR[low];
else
{
int mid = (low + high) / 2;
RcdType * TR2 = (RcdType *)malloc(sizeof(RcdType) * max_size);
if (TR2)
{
MSort( SR, TR2, low, mid, max_size);
MSort( SR, TR2, mid+1, high, max_size);
merge( TR2, TR, low, high, mid);
}
free(TR2);
}
}
void Merge_Sort(SqList&L)
{
MSort( L.r, L.r, 1, L.length, L.length+1);
}
//基数排序相关操作
int ord(int a,int i){//取第i个关键字
int e,t;
e=a;t=i;
while(t>1){e/=10;t--;}
e=e%10;
return e;
}
void Distribute(SLlist &H,int i,ArrType &f, ArrType &e){
int j;
int p,q;
for(j=0;j<RADIX;j++)f[j]=0;
for(p=H.r[0].next;p;p=H.r[p].next){
j=ord(H.r[p].key,i);
if(!f[j])f[j]=p;
else H.r[e[j]].next=p;
e[j]=p;
}
printf("第%d趟分配后顺序为:",i);
for (j=0;j<RADIX;j++)
{if(f[j])
{ p=f[j];q=e[j];
while(p!=q){printf("%d ",H.r[p].key); p=H.r[p].next;}
printf("%d ",H.r[q].key);
}
}printf("\n");
}
void Collect(SLlist &H,int i,ArrType &f,ArrType &e)
{
int j,t,k;
for (j=0;j<RADIX&&(f[j]==0);j++);
H.r[0].next=f[j]; t=e[j];
for (k=j+1;k<RADIX;k++)
if(f[k]) { H.r[t].next=f[k];t=e[k];}
H.r[t].next=0;
}
void printSList(SLlist &H)
{
printf("当前静态链表为:");
int i;
for(i=1;H.r[i].next;i=H.r[i].next)
printf("%d->",H.r[i].key);
printf("%d\n",H.r[i].key);
}
void RadixSort(SqList &L){//将顺序表L先转化为链表H,对H进行操作
SLlist H;
int i,k,t;
ArrType f,e;
H.recnum=L.length;
if(L.maxkey<10)
H.keynum=1;
else
if(L.maxkey<100)
H.keynum=2;
else if(L.maxkey<1000)
H.keynum=3;
else H.keynum=4;
H.r=(SLcell*)malloc(MAXSIZE*sizeof(SLcell));
for(i=0;i<H.recnum;i++){
H.r[i].next=i+1;
H.r[i+1].key=L.r[i+1].key;
}//将顺序表L先转化为链表H
H.r[H.recnum].next=0;
printSList(H);
for(i=1;i<=H.keynum;i++){
Distribute(H,i,f,e);
Collect(H,i,f,e);
}
t=H.r[0].next;
for(i=1;i<=L.length;i++){
L.r[i].key=H.r[t].key;
t=H.r[t].next;
}
}
void menu()
{
printf("|==================================|\n");
printf("| ****---- 选择式菜单 ----**** |\n");
printf("|==================================|\n");
printf("| |\n");
printf("| 1:插入类排序 |\n");
printf("| |\n");
printf("| 2:交换类排序 |\n");
printf("| |\n");
printf("| 3:选择类排序 |\n");
printf("| |\n");
printf("| 4:归并类排序 |\n");
printf("| |\n");
printf("| 5:基数排序 |\n");
printf("| |\n");
printf("| 0:退出菜单 |\n");
printf("| |\n");
printf("|==================================|\n");
}//menu
void menu1()
{
printf("|==================================|\n");
printf("| ****---插入类排序菜单---**** |\n");
printf("|==================================|\n");
printf("| |\n");
printf("| 1:直接插入排序 |\n");
printf("| |\n");
printf("| 2:折半插入排序 |\n");
printf("| |\n");
printf("| 3:希尔 |\n");
printf("| |\n");
printf("| 0:返回上层 |\n");
printf("| |\n");
printf("|==================================|\n");
}//menu1
void menu2()
{
printf("|==================================|\n");
printf("| ****---交换类排序菜单---**** |\n");
printf("|==================================|\n");
printf("| |\n");
printf("| 1:冒泡排序 |\n");
printf("| |\n");
printf("| 2:快速排序 |\n");
printf("| |\n");
printf("| 0:返回上层 |\n");
printf("| |\n");
printf("|==================================|\n");
}//menu2
void menu3()
{
printf("|==================================|\n");
printf("| ****---选择类排序菜单---**** |\n");
printf("|==================================|\n");
printf("| |\n");
printf("| 1:简单选择排序 |\n");
printf("| |\n");
printf("| 2:堆选择排序 |\n");
printf("| |\n");
printf("| 0:返回上层 |\n");
printf("| |\n");
printf("|==================================|\n");
}//menu3
int main() {
SqList L;
int k,k1,k2,k3;
int loop=1,loop1=1,loop2=1,loop3=1;
int dlta[3]={5,3,1};//希尔排序增量序列
while (loop) {
system("cls");
menu();
printf(" 请选择项号:");
scanf("%d",&k);
switch(k) {
case 0: loop = 0;
break;
case 1:
system("cls");
loop1=1;
while (loop1) {
menu1();
printf(" 请选择项号:");
scanf("%d",&k1);
switch(k1) {
case 0: loop1 = 0;
break;
case 1:
system("cls");
createList(L);
printf("\n直接插入排序前: ");
print_SqList(L);
insertsort(L);
printf("\n直接插入排序后: ");
print_SqList(L);
break;
case 2:
system("cls");
createList(L);
printf("\n折半插入排序前: ");
print_SqList(L);
insertsort_bin(L);
printf("\n折半插入排序后: ");
print_SqList(L);
break;
case 3:
system("cls");
createList(L);
printf("\n希尔排序前: ");
print_SqList(L);
ShellSort(L,dlta,3);
printf("\n希尔排序后: ");
print_SqList(L);
break;
default:system("cls");
printf("警告!你给的选项号非法,请重新输入\n");
}
}
break;
case 2:
system("cls");
loop2=1;
while (loop2) {
menu2();
printf("请选择项号:");
scanf("%d",&k2);
switch(k2) {
case 0: loop2 = 0;
break;
case 1:
system("cls");
createList(L);
printf("\n冒泡排序前: ");
print_SqList(L);
bublesort(L);
printf("\n冒泡排序后: ");
print_SqList(L);
break;
case 2:
system("cls");
createList(L);
printf("\n快速排序前: ");
print_SqList(L);
quicksort(L, 1, L.length);
printf("\n快速排序后: ");
print_SqList(L);
break;
default:system("cls");
printf("警告!你给的选项号非法,请重新输入\n");
}
}
break;
case 3:
system("cls");
loop3=1;
while (loop3) {
menu3();
printf("请选择项号:");
scanf("%d",&k3);
switch(k3) {
case 0: loop3 = 0;
break;
case 1:
system("cls");
createList(L);
printf("\n简单选择排序前: ");
print_SqList(L);
selectsort(L);
printf("\n简单选择排序后: ");
print_SqList(L);
break;
case 2:
system("cls");
createList(L);
printf("\n堆选择排序前: ");
print_SqList(L);
heapsort(L);
printf("\n堆选择排序后: ");
print_SqList(L);
break;
default:system("cls");
printf("警告!你给的选项号非法,请重新输入\n");
}
}
break;
case 4:
system("cls");
createList(L);
printf("\n归并排序前: ");
print_SqList(L);
Merge_Sort(L);
printf("\n归并排序后: ");
print_SqList(L);
system("pause");
break;
case 5:
system("cls");
createList(L);
printf("\n基数排序前: ");
print_SqList(L);
RadixSort(L);
printf("\n基数排序后: ");
print_SqList(L);
system("pause");
break;
default:system("cls");
printf("警告!你给的选项号非法,请重新输入\n");
}
}
return 0;
}