idk why these stuffs get stashed for so long and I didn't ever commit them
This commit is contained in:
580
OrigFiles/8-排序/Sort.cpp
Normal file
580
OrigFiles/8-排序/Sort.cpp
Normal file
@@ -0,0 +1,580 @@
|
||||
#include<iostream>
|
||||
//#include"assert.h"
|
||||
//#include"sort.h"
|
||||
using namespace std;
|
||||
|
||||
// 测试数据集,0单元未用
|
||||
int IA[9]={0,58,40,65,97,87,8,17,58}; // 直接插入、折半插入
|
||||
int SA[11]={0,58,40,65,97,87,8,17,58,46,60}; // 希尔
|
||||
int BA[9]={0,58,40,65,97,87,8,17,58}; // 冒泡
|
||||
int QA[9]={0,58,35,65,97,87,8,17,58}; // 快速
|
||||
int SSA[9]={0,58,35,25,97,87,8,58,17}; // 简单选择排序
|
||||
int HA[9]={0,38,25,16,36,18,32,28,50}; // 堆排序
|
||||
int EA1[8]={0,58,40,25,87,8,58,17}; // 归并
|
||||
int EA2[9]={0,8,4,5,2,6,3,7,9}; // 递归归并
|
||||
int RA[9]={0,769,763,63,249,243,545,281,89}; // 基数排序
|
||||
|
||||
|
||||
|
||||
void CopyData(int a[],int n, int R[]) // 数据后移一个单元,从1单元开始
|
||||
{
|
||||
for(int i=1;i<=n;i++)
|
||||
R[i]=a[i];
|
||||
}
|
||||
|
||||
void DispData(int R[], int n) // 数据显示
|
||||
{
|
||||
int i;
|
||||
for(i=1;i<=n;i++)
|
||||
cout<<R[i]<<'\t';
|
||||
cout<<endl;
|
||||
}
|
||||
|
||||
// 算法8.1 直接插入排序
|
||||
void InsertSort(int R[], int n)
|
||||
{
|
||||
int i, j;
|
||||
for(i=2; i<=n; i++) // 从第2个元素开始
|
||||
{
|
||||
if(R[i-1]>R[i]) // 1.如果R[i-1]>R[i]
|
||||
{
|
||||
R[0]=R[i]; // 1.1 R[i]复制为监视哨
|
||||
R[i]=R[i-1]; // 1.2 R[i]后移
|
||||
for(j=i-2;R[j]>R[0];--j) // 1.3 j从i-2开始,如果R[j]>R[0], R[j]后移,j--
|
||||
R[j+1]=R[j]; // 1.4 插入R[i],i++
|
||||
R[j+1]=R[0];
|
||||
}
|
||||
cout<<" 第 "<<i-1<<" 趟 \t"; // 显示每趟排序结果
|
||||
DispData(R,n);
|
||||
} // 2.否则,i++,进入下一趟
|
||||
}
|
||||
|
||||
//算法8.2 折半插入排序
|
||||
void BInsertSort(int R[],int n)
|
||||
{
|
||||
int i,j,m;
|
||||
int low,high;
|
||||
for(i=2; i<=n; i++) // n个记录,进行n-1趟
|
||||
{
|
||||
R[0]=R[i]; // 1.保存R[i]
|
||||
low=1; // 2.用折半查找方法,找插入点
|
||||
high=i-1; // 2.1 设置查找范围的下界和上界
|
||||
while(low<=high) // 2.2 只要low<=high
|
||||
{
|
||||
m=(low+high)/2; // 2.2.1计算中间位置m
|
||||
if(R[m]>R[i]) high=m-1; // 2.2.2 R[m]>R[0],调整查询上界
|
||||
else low=m+1; // 否则,调整查找下界
|
||||
} // 3.插入点high+1后元素移动
|
||||
for(j=i-1;j>=high+1;--j) // 3.1 R[i-1]~R[high+1]依次后移
|
||||
R[j+1]=R[j]; // 3.2 R[i]复制到R[high+1]
|
||||
R[high+1]=R[0];
|
||||
cout<<" 第 "<<i-1<<" 趟 \t"; // 显示每趟排序结果
|
||||
DispData(R,n);
|
||||
}
|
||||
}
|
||||
|
||||
//算法8.3 希尔排序
|
||||
|
||||
void ShellInsert(int R[],int n,int dk) // 增量为dk的一趟希尔排序
|
||||
{
|
||||
int i,j;
|
||||
for(i=dk+1;i<=n;++i)
|
||||
if(R[i]<R[i-dk]) // 通过下标间距控制一起插入排序的元素,d组同时进行。
|
||||
{
|
||||
R[0]=R[i];
|
||||
for(j=i-dk;j>0 && (R[0]<R[j]); j-=dk)
|
||||
R[j+dk]=R[j];
|
||||
R[j+dk]=R[0];
|
||||
}
|
||||
}
|
||||
|
||||
void ShellSort(int R[],int n,int d[],int t)
|
||||
{
|
||||
int k;
|
||||
for(k=0;k<t;k++) // t个增量
|
||||
{
|
||||
ShellInsert(R,n,d[k]); // 进行t趟
|
||||
cout<<" 第 "<<k+1<<" 趟 \t"; // 显示每趟排序结果
|
||||
DispData(R,n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//算法8.4 冒泡排序
|
||||
void Bubble_Sort(int R[],int n)
|
||||
{
|
||||
int i,j,temp;
|
||||
bool exchange;
|
||||
for(i=1,exchange=true;i<n && exchange; i++) // 增量为dk的一趟希尔排序操作结束。
|
||||
{ // 一趟排序工作如下:
|
||||
exchange=false; // 1.设置交换标志初值为无交换
|
||||
for(j=1;j<=n-i;j++) // 2.从表首开始两两比较
|
||||
{
|
||||
if (R[j]>R[j+1]) // 2.1相邻元素逆序,互换位置
|
||||
{
|
||||
temp=R[j],R[j]=R[j+1],R[j+1]=temp; // R[j]<-->R[j+1]
|
||||
exchange=true; // 2.2 交换标志改为true
|
||||
}
|
||||
}
|
||||
cout<<" 第 "<<i<<" 趟 \t"; // 显示每趟排序结果
|
||||
DispData(R,n);
|
||||
}
|
||||
}
|
||||
|
||||
//算法8.5 一次划分
|
||||
int Partition(int R[],int low,int high)
|
||||
{
|
||||
int pivot;
|
||||
pivot=R[low]; // 1. 第1个记录为枢轴
|
||||
while(low<high) // 2. 扫描完所有记录,退出循环
|
||||
{
|
||||
while(low<high && R[high]>=pivot) // 2.1 从高端做起,
|
||||
--high; // 2.1.1 比枢轴大,位置不动
|
||||
R[low]=R[high]; // 2.1.2 比枢轴小,记录移到低端
|
||||
while(low <high && R[low]<=pivot) // 2.2 转到低端,
|
||||
++low; // 2.2.1 比枢轴小,位置不动
|
||||
R[high]=R[low]; // 2.2.2 比枢轴大,记录移到高端
|
||||
cout<<endl; // 转至高端
|
||||
}
|
||||
R[low]=pivot; // 3. 扫描结束,枢轴记录定位
|
||||
return low; // 4. 返回枢轴位置。
|
||||
}
|
||||
|
||||
//算法8.6 快速排序递归算法
|
||||
void QSort(int R[],int low,int high) // 对R[n]进行快速排序
|
||||
{
|
||||
int pivoitloc;
|
||||
if(low<high) // 序列长度大于1,//进行下列操作
|
||||
{
|
||||
pivoitloc=Partition(R,low,high); // 1. 一次划分
|
||||
cout<<"枢轴元素:"<<R[pivoitloc]; // 轴出各趟枢轴元素
|
||||
QSort(R,low,pivoitloc-1); // 2. 对低子序列递归排序
|
||||
QSort(R,pivoitloc+1,high); // 3. 对高子序列递归排序
|
||||
}
|
||||
}
|
||||
|
||||
//算法8.7 简单选择排序
|
||||
void SelectSort(int R[],int n)//对R[n]进行简单选择排序
|
||||
{
|
||||
int i,j,t,mink;
|
||||
for(i=1;i<n;++i) // 共需n-1趟,每一趟操作如下:
|
||||
{
|
||||
mink=i; // 1.查找最小关键码记录号mink
|
||||
for(j=i+1;j<=n;++j)
|
||||
if(R[j]<R[mink])
|
||||
mink=j;
|
||||
if(mink!=i) // 2.如果最小记录不是第i个
|
||||
{
|
||||
t=R[i];R[i]=R[mink];R[mink]=t; // 3.R[i]←→R[mink]
|
||||
}
|
||||
cout<<" 第 "<<i<<" 趟 \t"; // 显示每趟排序结果
|
||||
DispData(R,n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//算法8.8 一次筛选
|
||||
void HeapAdjust(int R[],int s,int n) //将R[s..n]调整为以R[s]为根的大根堆
|
||||
|
||||
{
|
||||
int j;
|
||||
R[0]=R[s]; // 1.复制R[s],让出R[s]空间
|
||||
for(j=2*s;j<=n;j=2*s) // 2.一次筛选
|
||||
{
|
||||
if(j<n && R[j]<R[j+1]) // 2.1比较子树根的两个孩子,取较大者
|
||||
j++;
|
||||
if(R[0]>R[j]) // 2.2子树根大于较大者,无需记录移动
|
||||
break;
|
||||
R[s]=R[j]; // 2.3 否则,R[j]为子树根
|
||||
s=j; // 2.4 考量下一级子树,
|
||||
}
|
||||
R[s]=R[0]; // R[s]插入到合适位置
|
||||
}
|
||||
|
||||
//算法8.9 建堆
|
||||
void CreateHeap(int R[],int n) //把无序序列R[1..n]建成大根堆
|
||||
{
|
||||
int i;
|
||||
for(i=n/2;i>0;--i) // 从首个非叶结点开始
|
||||
{
|
||||
HeapAdjust(R,i,n); // 反复调用HeapAdjust,逐个调整。
|
||||
}
|
||||
cout<<" 堆 :\t"; // 输出堆
|
||||
DispData(R,n);
|
||||
}
|
||||
|
||||
//算法8.10 堆排序
|
||||
void HeapSort(int R[],int n)
|
||||
{
|
||||
int i,t;
|
||||
CreateHeap(R,n); // 建堆
|
||||
for(i=1;i<n;i++)
|
||||
{
|
||||
t=R[1];R[1]=R[n-i+1];R[n-i+1]=t; // 堆顶与堆尾元素互换位置
|
||||
cout<<" 第 "<<i<<" 趟 \t"; // 显示每趟排序结果
|
||||
DispData(R,n);
|
||||
HeapAdjust(R,1,n-i); // 调整成堆
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//算法8.11 两个有序列合并
|
||||
void Merge(int R[],int s, int m, int t) // 两个有序序列R[s..m]、R[m+1..t]合并一个有序序列
|
||||
{
|
||||
int *R1; // 1. 初始化
|
||||
int i,j,n,k;
|
||||
n=t+1; //1.1辅助数组临存归并结果
|
||||
R1=new int[n]; // 1.2 设3个工作指针i、j、k分别指向R[s]、R[m+1]、R1[]首元处
|
||||
i=s;
|
||||
j=m+1;
|
||||
k=s;
|
||||
while(i<=m && j<=t) // 2.两个序列合并:2.1两个序列均不空
|
||||
{
|
||||
if(R[i]<=R[j])
|
||||
R1[k++]=R[i++];
|
||||
else
|
||||
R1[k++]=R[j++];
|
||||
}
|
||||
while(i<=m) // 2.2若第1个子序列未处理完,R[m+1..t]为剩余记录
|
||||
R1[k++]=R[i++];
|
||||
while(j<=t) // 2.3若第2个子序列未处理完,将其剩余部分复制到R1
|
||||
R1[k++]=R[j++];
|
||||
for(k=s,i=s;i<=t;k++,i++) // 3.将R1复制到R[s..t]中
|
||||
R[i]=R1[k];
|
||||
delete R1; // 释放R1。
|
||||
}
|
||||
|
||||
|
||||
//算法8.12 一趟归并
|
||||
void MergePass(int R[],int n,int len)
|
||||
{
|
||||
int i=1; // 序列下标从1开始
|
||||
while(i+2*len-1<=n) // 等长子序列合并
|
||||
{
|
||||
Merge(R,i,i+len-1,i+2*len-1);
|
||||
i+=2*len;
|
||||
}
|
||||
if(i+len-1<n) // 不等长子序列
|
||||
Merge(R,i,i+len-1,n);
|
||||
}
|
||||
|
||||
|
||||
//算法8.13 2-路归并算法
|
||||
void MergeSort(int R[],int n)
|
||||
{
|
||||
int len;
|
||||
for(len=1;len<=n;len=len*2) // 初始子序列长度为1
|
||||
{
|
||||
MergePass(R,n,len); // 子序列合并
|
||||
cout<<" 第 "<<len/2+1<<" 趟 \t"; // 显示每趟排序结果
|
||||
DispData(R,n);
|
||||
}
|
||||
}
|
||||
|
||||
//算法8.14 2-路归并递归算法
|
||||
void MSort(int R[],int s,int t)
|
||||
{
|
||||
int m; //1.待排序记录只有1个,递归结束
|
||||
if(s<t)
|
||||
{
|
||||
m=(s+t)/2; //2. 序列对半分
|
||||
MSort(R,s,m); //3. 递归归并前半个子序列
|
||||
MSort(R,m+1,t); //4. 递归归并后半个子序列
|
||||
Merge(R,s,m,t); //5. 左、右两个子序列归并
|
||||
}
|
||||
}
|
||||
|
||||
void MergeSort1(int R[], int n)
|
||||
{
|
||||
MSort(R,1,n); // 初次调用
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct RNode // 多关键字结点
|
||||
{
|
||||
int keys[3]; // 设关键字数为d=3
|
||||
struct RNode *next;
|
||||
};
|
||||
|
||||
|
||||
void CreateDL(RNode *&L,int R[],int n) // 尾插法建无头结点单链表,存储待排序记录
|
||||
{
|
||||
int i;
|
||||
RNode *p,*rr;
|
||||
for(i=1;i<=n;i++)
|
||||
{
|
||||
p=new RNode;
|
||||
//cout<<"R[i]"<<R[i]<<'\t';
|
||||
p->keys[0]=R[i]/100; // 百位
|
||||
p->keys[1]=R[i]%100/10; // 十位
|
||||
p->keys[2]=R[i]%100%10; // 个位
|
||||
p->next=NULL;
|
||||
if (i==1) // 首元结点
|
||||
{
|
||||
L=p;
|
||||
rr=L;
|
||||
}
|
||||
else // 非首元结点
|
||||
{
|
||||
rr->next=p;
|
||||
rr=p;
|
||||
}
|
||||
cout<<endl;
|
||||
}
|
||||
}
|
||||
|
||||
void DispDL(RNode *L)
|
||||
{
|
||||
int d;
|
||||
RNode *p;
|
||||
p=L;
|
||||
while(p!=NULL)
|
||||
{
|
||||
for(d=0;d<3;d++)
|
||||
cout<<p->keys[d];
|
||||
cout<<'\t';
|
||||
p=p->next;
|
||||
}
|
||||
cout<<endl;
|
||||
}
|
||||
|
||||
//算法8.15 基数排序
|
||||
void RadixSort(RNode *&L,int r,int d) // r进制数、d位数的基排序
|
||||
{
|
||||
int i,j,k;
|
||||
RNode *h[10],*t[10],*T; // 10进制数,建立10个队列
|
||||
for(i=d-1;i>=0;i--) // d个数位d个关键字,d趟
|
||||
{ // 每一趟
|
||||
for(j=0;j<r;j++) // 1.队列初始化
|
||||
h[j]=t[j]=NULL;
|
||||
while(L!=NULL) // 2.扫描序列列表,进行分
|
||||
{
|
||||
k=L->keys[i]; // 2.1第i个子关键字为k则入第k个队列
|
||||
if(h[k]==NULL) // 2.1.1首元结点,
|
||||
{
|
||||
h[k]=L;t[k]=L; // 队尾指向队头
|
||||
}
|
||||
else // 2.1.2非首元结点,
|
||||
{
|
||||
t[k]->next=L; t[k]=L; // 入队尾
|
||||
}
|
||||
L=L->next; // 2.2 取一下待排序记录
|
||||
}
|
||||
L=NULL; // 收集
|
||||
for(j=0;j<r;j++) // 3.1 r个队列,尾-首相连
|
||||
{
|
||||
if(h[j]!=NULL) // 3.1.2首元结点
|
||||
{
|
||||
if(L==NULL) // 队尾指向队头
|
||||
{
|
||||
L=h[j];T=t[j];
|
||||
}
|
||||
else // 3.1.3 非首元结点,
|
||||
{
|
||||
T->next=h[j];T=t[j]; // 首尾相接
|
||||
}
|
||||
}
|
||||
}
|
||||
T->next=NULL; // 尾结点,next为空
|
||||
cout<<" 第 "<<d-i<<" 趟 "<<'\t';
|
||||
DispDL(L);
|
||||
}
|
||||
}
|
||||
|
||||
void dispmenu()
|
||||
{
|
||||
cout<<"* 主 菜 单 *"<<endl;
|
||||
cout<<"---------------"<<endl;
|
||||
cout<<"* 插 入 排 序 * "<<endl
|
||||
<<" 1 直接插入排序"<<endl
|
||||
<<" 2 折半插入排序"<<endl
|
||||
<<" 3 希尔排序"<<endl
|
||||
<<endl;
|
||||
cout<<"* 交 换 排 序 *"<<endl
|
||||
<<" 4 起泡排序"<<endl
|
||||
<<" 5 快速排序"<<endl
|
||||
<<endl;
|
||||
cout<<"* 选 择 排 序 *"<<endl
|
||||
<<" 6 简单选择排序"<<endl
|
||||
<<" 7 堆排序"<<endl
|
||||
<<endl;
|
||||
cout<<" 8 归并排序"<<endl
|
||||
<<" 9 基数排序"<<endl
|
||||
<<" 0 退出程序"<<endl;
|
||||
cout<<"请选择主菜单:";
|
||||
}
|
||||
|
||||
|
||||
// 主函数
|
||||
int main()
|
||||
{
|
||||
int n;
|
||||
system("cls"); // 清屏
|
||||
|
||||
int choice;
|
||||
do
|
||||
{
|
||||
dispmenu(); // 显示主菜单
|
||||
cout<<endl;
|
||||
cout<<"Enter choice(1~10,0 退出):";
|
||||
cin>>choice;
|
||||
switch(choice)
|
||||
{
|
||||
case 1: // 直接插入排序
|
||||
{
|
||||
cout<<"直接插入排序"<<endl;
|
||||
cout<<endl;
|
||||
n=8;
|
||||
int R[9];
|
||||
CopyData(IA,n,R); // IA[]-->R
|
||||
cout<<"初始序列"<<'\t'; // 显示初始序列
|
||||
DispData(R,n);
|
||||
InsertSort(R,n); // 直接插入排序
|
||||
;
|
||||
break;
|
||||
}
|
||||
case 2: // 折半插入排序
|
||||
{
|
||||
cout<<"折半插入排序"<<endl;
|
||||
cout<<endl;
|
||||
n=8;
|
||||
int R[9];
|
||||
CopyData(IA,n,R); // IA[]-->R
|
||||
cout<<"初始序列"<<'\t'; // 显示初始序列
|
||||
DispData(R,n);
|
||||
BInsertSort(R,n); // 折半插入排序
|
||||
cout<<endl;
|
||||
break;
|
||||
}
|
||||
case 3: // 希尔排序
|
||||
{
|
||||
cout<<"希尔排序"<<endl;
|
||||
cout<<endl;
|
||||
int d[3]={5,3,1}; // d值
|
||||
n=10;
|
||||
int R[11];
|
||||
CopyData(SA,n,R); // SA[]-->R[]
|
||||
cout<<"初始序列"<<'\t';
|
||||
DispData(R,n); // 显示初始序列
|
||||
ShellSort(R,n,d,3); // 希尔排序
|
||||
break;
|
||||
}
|
||||
case 4: // 冒泡排序
|
||||
{
|
||||
cout<<"冒泡排序"<<endl;
|
||||
cout<<endl;
|
||||
n=8;
|
||||
int R[9];
|
||||
CopyData(BA,n,R); // BA[]-->R[]
|
||||
cout<<"初始序列"<<'\t'; // 显示初始序列
|
||||
DispData(R,n);
|
||||
Bubble_Sort(R,n); // 冒泡排序
|
||||
break;
|
||||
}
|
||||
case 5: // 快速排序
|
||||
{
|
||||
cout<<"快速排序"<<endl;
|
||||
cout<<endl;
|
||||
//n=sizeof(QA)/sizeof(QA[0]);
|
||||
n=8;
|
||||
int R[9];
|
||||
CopyData(QA,n,R); // QA[]-->R[]
|
||||
cout<<"初始序列"<<'\t'; // 显示初始序列
|
||||
DispData(R,n);
|
||||
QSort(R,1,n); // 快速排序
|
||||
cout<<endl;
|
||||
cout<<"有序序列\t";
|
||||
DispData(R,n); // 排序结果
|
||||
break;
|
||||
}
|
||||
case 6: // 简单选择排序
|
||||
{
|
||||
cout<<"简单选择排序"<<endl;
|
||||
cout<<endl;
|
||||
n=8;
|
||||
int R[9];
|
||||
CopyData(SSA,n,R); // SSA[]-->R[]
|
||||
cout<<"初始序列"<<'\t'; // 显示初始序列
|
||||
DispData(R,n);
|
||||
SelectSort(R,n); // 简单选择排序
|
||||
break;
|
||||
}
|
||||
case 7: // 堆排序
|
||||
{
|
||||
cout<<"堆排序"<<endl;
|
||||
cout<<endl;
|
||||
n=8;
|
||||
int R[9];
|
||||
CopyData(HA,n,R); // HA[]-->R[]
|
||||
cout<<"初始序列"<<'\t'; // 显示初始序列
|
||||
DispData(R,n);
|
||||
HeapSort(R,n); // 堆排序
|
||||
cout<<endl;
|
||||
break;
|
||||
}
|
||||
case 8: // 二路归并排序
|
||||
{
|
||||
int n1,n2;
|
||||
cout<<endl;
|
||||
cout<<"归并排序(非递归)"<<endl; // 二路归非递归并排序
|
||||
cout<<endl;
|
||||
n1=7;
|
||||
int R1[8];
|
||||
CopyData(EA1,n1,R1); // EA1-->R1
|
||||
cout<<"初始序列"<<'\t'; // 显示初始序列
|
||||
DispData(R1,n1);
|
||||
MergeSort(R1,n1); // 二路归递归并排序
|
||||
cout<<"归并排序(递归)"<<endl;
|
||||
cout<<endl;
|
||||
n2=8;
|
||||
int R2[9];
|
||||
CopyData(EA2,n2,R2); // EA2-->R2
|
||||
cout<<"初始序列"<<'\t'; // 显示初始序列
|
||||
DispData(R2,n2);
|
||||
MergeSort1(R2,n2);
|
||||
cout<<"有序序列\t";
|
||||
DispData(R2,n2); // 排序结果
|
||||
break;
|
||||
}
|
||||
case 9: // 基数排序
|
||||
{
|
||||
int r,d;
|
||||
r=10; // 十进制数
|
||||
d=3; // 3个关键字
|
||||
RNode *L; // 链式存储,无头结点
|
||||
L=NULL; // 空表
|
||||
cout<<"基排序"<<endl;
|
||||
cout<<endl;
|
||||
n=8;
|
||||
int R[9];
|
||||
CopyData(RA,n,R); // RA-->R
|
||||
cout<<"测试数据:";
|
||||
DispData(R,n); // 显示初始序列
|
||||
CreateDL(L,R,n); // 创建链表
|
||||
cout<<"初始序列"<<'\t'; // 显示链表
|
||||
DispDL(L);
|
||||
RadixSort(L,r,d); // 基数排序
|
||||
cout<<"有序序列\t"; // 显示排序结果
|
||||
DispDL(L);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0://退出
|
||||
;
|
||||
cout<<"结束运行"<<endl;
|
||||
break;
|
||||
default://非法选择
|
||||
cout<<"Invalid choice\n";
|
||||
break;
|
||||
}
|
||||
}while(choice!=0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
519
OrigFiles/8-排序/sort.h
Normal file
519
OrigFiles/8-排序/sort.h
Normal file
@@ -0,0 +1,519 @@
|
||||
//第十章 内部排序
|
||||
|
||||
|
||||
|
||||
//
|
||||
|
||||
//一(1)插入排序
|
||||
|
||||
void InsertSort(SqList<type> & L)
|
||||
{//对顺序表L作直接插入排序
|
||||
for(int i=2;i<=L.length;i++)
|
||||
if(L.key[i]<=L.key[i-1])//"<"需将L.key[i]插入有序子表
|
||||
{
|
||||
L.key[0]=L.key[i];//复制为哨兵
|
||||
L.key[i]=L.key[i-1];
|
||||
for(int j=i-2;L.key[0]<=L.key[j];--j)
|
||||
L.key[j+1]=L.key[j];//记录后移
|
||||
L.key[j+1]=L.key[0];//插入到正确位置
|
||||
}
|
||||
}
|
||||
|
||||
//(2)折半插入排序
|
||||
template<class type>
|
||||
void BInsertSort(SqList<type> &L)
|
||||
{//对顺序表L作折半插入排序
|
||||
int high,low,m;
|
||||
for(int i=2;i<=L.length;i++)
|
||||
{
|
||||
L.key[0]=L.key[i];//将L.key[i]暂存到L.key[0]
|
||||
low=1;
|
||||
high=i-1;
|
||||
while(low<=high)//在key[low]到key[high]中折半查找有序插入的位置
|
||||
{
|
||||
m=(low+high)/2;//折半
|
||||
if(L.key[0]<=L.key[m])
|
||||
high=m-1;//插入低半区
|
||||
else
|
||||
low=m+1;//插入高半区
|
||||
}
|
||||
for(int j=i-1;j>=high+1;--j)
|
||||
L.key[j+1]=L.key[j]; //记录后移
|
||||
L.key[high+1]=L.key[0]; //插入
|
||||
}
|
||||
}
|
||||
//(3)表插入排序
|
||||
const int SIZE=100;//静态链表最大容量
|
||||
const int MAXINT=10000;
|
||||
template<class type>
|
||||
struct StaListNode{
|
||||
type data;//记录项
|
||||
int next;//指针项
|
||||
};
|
||||
template<class type>
|
||||
class StaticList{
|
||||
public:
|
||||
StaListNode<type> node[SIZE];
|
||||
int curlen;//链表实际长度
|
||||
StaticList()//构造函数
|
||||
{
|
||||
cout<<"建立静态链表"<<endl;
|
||||
cout<<"请输入静态链表的实际长度:"<<endl;
|
||||
cin>>curlen;
|
||||
cout<<"请输入各结点数据:"<<endl;
|
||||
node[0].data=MAXINT;
|
||||
node[0].next=0;
|
||||
for(int i=1;i<=curlen;i++)
|
||||
{
|
||||
node[i].next=0;
|
||||
cin>>node[i].data;
|
||||
}
|
||||
}
|
||||
~StaticList()//析构函数
|
||||
{
|
||||
}
|
||||
};
|
||||
void StaListInsertSort()
|
||||
{
|
||||
StaticList<int> sl;
|
||||
int min,max;//标记最大值最小值
|
||||
sl.node[0].next=1;
|
||||
sl.node[1].next=0;//初始化形成只有头结点的循环链表
|
||||
max=min=1;
|
||||
for(int i=2;i<=sl.curlen;i++)//向有序循环链表中加入结点,共n-1趟
|
||||
{
|
||||
|
||||
if(sl.node[i].data<=sl.node[min].data)
|
||||
{
|
||||
sl.node[0].next=i;
|
||||
sl.node[i].next=i-1;
|
||||
min=i;
|
||||
}
|
||||
if(sl.node[i].data>=sl.node[max].data)
|
||||
{
|
||||
sl.node[i].next=0;
|
||||
sl.node[max].next=i;
|
||||
max=i;
|
||||
}
|
||||
if(sl.node[i].data<sl.node[max].data&&sl.node[i].data>sl.node[min].data)
|
||||
{
|
||||
int index1=min,index2;//index2用来标记index1的前一个下标
|
||||
while(sl.node[i].data>=sl.node[index1].data)
|
||||
{
|
||||
index2=index1;
|
||||
index1=sl.node[index1].next;
|
||||
}
|
||||
sl.node[i].next=index1;
|
||||
sl.node[index2].next=i;
|
||||
}
|
||||
|
||||
}
|
||||
cout<<"表插入排序结果如下:"<<endl;
|
||||
int index=sl.node[0].next;
|
||||
while(index!=0)
|
||||
{
|
||||
cout<<sl.node[index].data<<"\t";
|
||||
index=sl.node[index].next;
|
||||
}
|
||||
cout<<endl;
|
||||
}
|
||||
//(4)希尔排序
|
||||
template<class type>
|
||||
void ShellInsert(SqList<type> &L,int dk)
|
||||
{//对顺序表进行一趟希尔插入排序
|
||||
for(int i=dk+1;i<=L.length;i++)
|
||||
if(L.key[i]<=L.key[i-dk])
|
||||
{
|
||||
L.key[0]=L.key[i];
|
||||
for(int j=i-dk;j>0&&L.key[0]<=L.key[j];j-=dk)
|
||||
L.key[j+dk]=L.key[j];
|
||||
L.key[j+dk]=L.key[0];
|
||||
}
|
||||
}
|
||||
template<class type>
|
||||
void ShellSort(SqList<type> &L,int dlta[],int t)
|
||||
{
|
||||
//按增量序列dl[0]--dl[t-1]对顺序表L作哈希排序
|
||||
for(int k=0;k<t;k++)
|
||||
ShellInsert(L,dlta[k]);
|
||||
}
|
||||
//二快速排序
|
||||
//(1)起泡排序
|
||||
template<class type>
|
||||
void BubbleSort(SqList<type> & L)
|
||||
{
|
||||
for(int i=1;i<L.length;i++)//用i控制比较趟数共n-1趟
|
||||
{
|
||||
type t;
|
||||
for(int j=1;j<=L.length-i;j++)
|
||||
if(L.key[j]>L.key[j+1])
|
||||
{
|
||||
t=L.key[j];
|
||||
L.key[j]=L.key[j+1];
|
||||
L.key[j+1]=t;
|
||||
}
|
||||
}
|
||||
}
|
||||
//(2)快速排序
|
||||
template<class type>
|
||||
int Partition(SqList<type>& L,int low,int high)
|
||||
{//交换顺序表L中子表key[low]--key[high]中的记录,枢轴记录到位,并返回其所在位置,
|
||||
//此时在它之前(后)的记录均不大(小)于它
|
||||
type pivotkey;
|
||||
L.key[0]=L.key[low];//用子表的第一个记录作枢轴记录
|
||||
pivotkey=L.key[low];//关键字
|
||||
while(low<high)//从表的两端交替向中间扫描
|
||||
{
|
||||
while(low<high&&L.key[high]>=pivotkey) --high;
|
||||
L.key[low]=L.key[high];//将比枢轴小的记录移至低端
|
||||
while(low<high&&L.key[low]<=pivotkey) ++low;
|
||||
L.key[high]=L.key[low];//将比枢轴大的记录移至高端
|
||||
}
|
||||
L.key[low]=L.key[0];//枢轴记录到位
|
||||
return low;//返回枢轴位置
|
||||
}
|
||||
template<class type>
|
||||
void QSort(SqList<type>& L,int low,int high)
|
||||
{
|
||||
int mid;//接收枢轴位置
|
||||
if(low<high)
|
||||
{
|
||||
mid=Partition(L,low,high);
|
||||
QSort(L,low,mid-1);//对低子表进行排序
|
||||
QSort(L,mid+1,high);//对高子表进行排序
|
||||
}
|
||||
}
|
||||
template<class type>
|
||||
void QuitSort(SqList<type>& L)//对顺序表进行快速排序
|
||||
{
|
||||
QSort(L,1,L.length);
|
||||
|
||||
}
|
||||
//三选择排序
|
||||
//(1)简单选择排序
|
||||
template<class type>
|
||||
int SelectMinKey(SqList<type>& L,int n)
|
||||
{
|
||||
int min=n;
|
||||
type minkey;//最小值
|
||||
minkey=L.key[n];
|
||||
for(int i=n+1;i<=L.length;i++)
|
||||
if(L.key[i]<minkey)
|
||||
{
|
||||
minkey=L.key[i];
|
||||
min=i;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
template<class type>
|
||||
void SelectSort(SqList<type>& L)
|
||||
{
|
||||
//对顺序表L作简单选择排序
|
||||
int j;
|
||||
type t;
|
||||
for(int i=1;i<=L.length;i++)
|
||||
{
|
||||
j=SelectMinKey(L,i);//在L.key[i]--L.key[L.length]中选择最小的记录并将其地址赋给j
|
||||
if(i!=j)//交换记录
|
||||
{
|
||||
t=L.key[i];
|
||||
L.key[i]=L.key[j];
|
||||
L.key[j]=t;
|
||||
}
|
||||
}
|
||||
}
|
||||
//(2)树形选择排序
|
||||
|
||||
template<class type>
|
||||
class TreeNode{
|
||||
public:
|
||||
type data;//结点数据值
|
||||
int index;//树中位置
|
||||
int active;//是否继续比较标志
|
||||
TreeNode<type>& operator=(TreeNode<type>& treenode)
|
||||
{
|
||||
this->data=treenode.data;
|
||||
this->index=treenode.index;
|
||||
this->active=treenode.active;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
template<class type>
|
||||
void ChangeTree(TreeNode<type>*tree,int i)
|
||||
{
|
||||
if(i%2==0)
|
||||
tree[(i-1)/2]=tree[i-1];//当i为偶数时,和左结点比较
|
||||
else
|
||||
tree[(i-1)/2]=tree[i+1];//当i为奇数时,和右结点比较
|
||||
i=(i-1)/2;//重新比较,i上升到父亲结点位置
|
||||
int j;
|
||||
while(i)
|
||||
{
|
||||
if(i%2==0)//确定i的比较结点位置
|
||||
j=i-1;
|
||||
else
|
||||
j=i+1;
|
||||
if(!tree[i].active||!tree[j].active)
|
||||
if(tree[i].active)
|
||||
tree[(i-1)/2]=tree[i];
|
||||
else
|
||||
tree[(i-1)/2]=tree[j];
|
||||
else
|
||||
if(tree[i].data<tree[j].data)
|
||||
tree[(i-1)/2]=tree[i];
|
||||
else
|
||||
tree[(i-1)/2]=tree[j];
|
||||
i=(i-1)/2;
|
||||
}
|
||||
|
||||
}
|
||||
int Power(int n)//计算2的n次方
|
||||
{
|
||||
int result=1;
|
||||
if(n>=1)
|
||||
{
|
||||
for(int i=1;i<=n;i++)
|
||||
result*=2;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
int LeapNum(int n)//计算满足满二叉树的叶子结点总数
|
||||
{
|
||||
for(int i=1;i<100;i++)
|
||||
if(Power(i-1)<n&&n<Power(i))
|
||||
return Power(i);
|
||||
else if(Power(i-1)==n)
|
||||
return Power(i-1);
|
||||
}
|
||||
template<class type>
|
||||
void TreeSort(type a[],int n)
|
||||
{//本排序方法只适用于满二叉树
|
||||
TreeNode<type>* tree;
|
||||
int bottsize=LeapNum(n);//树底层结点个数,此处必须满足满二叉树
|
||||
int size=2*bottsize-1;//树中结点总数
|
||||
int externalindex=bottsize-1;//开始进行比较的结点位置
|
||||
tree=new TreeNode<type>[size];
|
||||
assert(tree);
|
||||
int j=0;
|
||||
for(int i=externalindex;i<size;i++)
|
||||
{
|
||||
tree[i].index=i;//下标赋值
|
||||
if(j<n)
|
||||
{
|
||||
tree[i].active=1;//设置访问标志。可以访问
|
||||
tree[i].data=a[j++];//载入数据
|
||||
}
|
||||
else
|
||||
tree[i].active=0;//额外结点设置成active=0
|
||||
}
|
||||
i=externalindex;
|
||||
while(i)//比较找到最小结点
|
||||
{
|
||||
j=i;
|
||||
while(j<2*i)
|
||||
{
|
||||
if(!tree[j+1].active||tree[j].data<=tree[j+1].data)
|
||||
{
|
||||
if(!tree[j+1].active&&!tree[j].active)
|
||||
tree[(j-1)/2].active=0;//其孩子结点都是额外结点的结点不可访问
|
||||
tree[(j-1)/2]=tree[j];//较小结点赋值给其双亲结点
|
||||
}
|
||||
else
|
||||
tree[(j-1)/2]=tree[j+1];
|
||||
j+=2;
|
||||
}
|
||||
i=(i-1)/2;
|
||||
}
|
||||
for(i=0;i<n-1;i++)//处理前面n-1个结点
|
||||
{
|
||||
a[i]=tree[0].data;
|
||||
tree[tree[0].index].active=0;//不在参加比较
|
||||
ChangeTree(tree,tree[0].index);//修改树结构
|
||||
}
|
||||
a[n-1]=tree[0].data;//处理数值最大的结点
|
||||
}
|
||||
template<class type>
|
||||
void OutPut(type a[],int n)//输出函数
|
||||
{
|
||||
for(int i=0;i<n;i++)
|
||||
cout<<a[i]<<"\t";
|
||||
cout<<endl;
|
||||
}
|
||||
//堆排序
|
||||
template<class type>
|
||||
void HeapAdjust(SqList<type>& L,int s,int m)
|
||||
{//对顺序表做查找,从值最大的孩子结点向下筛选,找到最大值
|
||||
type rc=L.key[s];
|
||||
for(int j=2*s;j<=m;j*=2)
|
||||
{
|
||||
if(j<m&&L.key[j]<=L.key[j+1])//找到值相对较大的孩子结点,并依次向下筛选
|
||||
j++;
|
||||
if(rc>L.key[j]) break;//如果rc最大则推出while循环
|
||||
L.key[s]=L.key[j];//最大值赋值
|
||||
s=j;//交换位置
|
||||
}
|
||||
L.key[s]=rc;
|
||||
}
|
||||
template<class type>
|
||||
void HeapSort(SqList<type>& L)
|
||||
{//对顺序表L进行堆排序
|
||||
type value;
|
||||
for(int i=L.length/2;i>0;i--)//把L.key[1...L.length]调整为大顶堆
|
||||
HeapAdjust(L,i,L.length);
|
||||
for(i=L.length;i>1;--i)
|
||||
{
|
||||
value=L.key[1];
|
||||
L.key[1]=L.key[i];
|
||||
L.key[i]=value;
|
||||
HeapAdjust(L,1,i-1);//将L.key[1...i-1]重新调整为大顶堆
|
||||
}
|
||||
|
||||
}
|
||||
//四
|
||||
//归并排序
|
||||
template<class type>
|
||||
void Merge(type *SR,type *TR,int i,int m,int n)
|
||||
{//将有序的SR[i...m]和SR[m+1...n]归并为有序的TR[i...n]
|
||||
for(int j=m+1,k=i;i<=m&&j<=n;k++)//将SR中的记录由大到小并入TR
|
||||
{
|
||||
if(SR[i]<=SR[j])
|
||||
TR[k]=SR[i++];
|
||||
else
|
||||
TR[k]=SR[j++];
|
||||
}
|
||||
if(i<=m)//将剩余的SR[i...m]赋值到TR
|
||||
for(int a=i;a<=m;a++)
|
||||
TR[k++]=SR[a];
|
||||
else if(j<=n)//将剩余的SR[j...n]复制到TR
|
||||
for(int b=j;b<=n;b++)
|
||||
TR[k++]=SR[b];
|
||||
}
|
||||
template<class type>
|
||||
void MSort(type *SR,type *TR1,int s,int t)
|
||||
{
|
||||
type TR2[100];//数组大小可以根据实际情况重新定义
|
||||
int m;
|
||||
//将SR[s...t]归并排序为TR[s...t]
|
||||
if(s==t)
|
||||
TR1[s]=SR[s];
|
||||
else
|
||||
{
|
||||
m=(s+t)/2;//将SR[s...t]平分为SR[s...m]和SR[m+1...t]
|
||||
MSort(SR,TR2,s,m);//递归地将SR[s...m]归并为有序的TR2[s...m]
|
||||
MSort(SR,TR2,m+1,t);//递归地将SR[m+1...t]归并为TR2[m+1...t]
|
||||
Merge(TR2,TR1,s,m,t);//将TR2[s...m]和TR2[m+1...t]归并到TR1[s...t]
|
||||
}
|
||||
}
|
||||
template<class type>
|
||||
void MergeSort(SqList<type> &L)
|
||||
{//对顺序表L作归并排序
|
||||
MSort(L.key,L.key,1,L.length);
|
||||
}
|
||||
//五 基数排序
|
||||
//链式基数排序
|
||||
const RADIX=10;
|
||||
typedef int ArrType[RADIX];
|
||||
ArrType f,e;
|
||||
template<class type>
|
||||
struct SLCell{
|
||||
type *keys;
|
||||
int next;
|
||||
};
|
||||
template<class type>
|
||||
struct SLList{
|
||||
SLCell<type>* SList;
|
||||
int keynum;
|
||||
int recnum;
|
||||
};
|
||||
template<class type>
|
||||
void InitSLList(SLList<type>& SL)//创建静态链表
|
||||
{
|
||||
cout<<"建立静态链表"<<endl<<"请输入数据个数:"<<endl;
|
||||
cin>>SL.recnum;
|
||||
SL.SList=new SLCell<type>[SL.recnum+1];
|
||||
assert(SL.SList);
|
||||
cout<<"请输入关键字项数"<<endl;
|
||||
cin>>SL.keynum;
|
||||
for(int i=1;i<=SL.recnum;i++)
|
||||
{
|
||||
SL.SList[i].keys=new type[SL.keynum+1];
|
||||
assert(SL.SList[i].keys);
|
||||
}
|
||||
SL.SList[0].next=1;
|
||||
cout<<"请输入数据"<<endl;
|
||||
for(i=1;i<=SL.recnum;i++)
|
||||
{
|
||||
cout<<"请输入第"<<i<<"个数据"<<endl;
|
||||
for(int j=1;j<=SL.keynum;j++)
|
||||
cin>>SL.SList[i].keys[j];
|
||||
if(i!=SL.recnum)
|
||||
SL.SList[i].next=i+1;
|
||||
else
|
||||
SL.SList[i].next=0;
|
||||
}
|
||||
}
|
||||
template<class type>
|
||||
void RelList(SLList<type> &SL)//释放内存空间
|
||||
{
|
||||
for(int i=1;i<=SL.recnum;i++)
|
||||
delete SL.SList[i].keys;
|
||||
delete SL.SList;
|
||||
}
|
||||
|
||||
|
||||
template<class type>
|
||||
void OutPut(SLList<type>& SL)//输出静态链表
|
||||
{
|
||||
for(int i=SL.SList[0].next;i;i=SL.SList[i].next)
|
||||
{
|
||||
//cout<<i<<endl;
|
||||
for(int j=1;j<=SL.keynum;j++)
|
||||
cout<<SL.SList[i].keys[j];
|
||||
cout<<'\t';
|
||||
}
|
||||
cout<<endl;
|
||||
}
|
||||
template<class type>
|
||||
void Distrbute(SLCell<type>* r,int i,ArrType &f,ArrType& e)
|
||||
{//按第i个关键字keys[i]建立RADIX个子表,使同一子表中记录的keys[i]相同
|
||||
//f[0...RADIX]和e[0...RADIX]分别指向各个子表中第一个和最后一个记录
|
||||
int j;
|
||||
for(j=0;j<RADIX;j++)//各子表初始化为空
|
||||
f[j]=0;
|
||||
for(int a=r[0].next;a;a=r[a].next)
|
||||
{
|
||||
j=r[a].keys[i];
|
||||
if(!f[j])
|
||||
f[j]=a;
|
||||
else
|
||||
r[e[j]].next=a;
|
||||
e[j]=a;
|
||||
}
|
||||
}
|
||||
template<class type>
|
||||
void Collect(SLCell<type>* r,int i,ArrType &f,ArrType& e)
|
||||
{//按keys[i]自小至大将f[0...RADIX]所指各个子表依次链接成一个链表
|
||||
int j;
|
||||
for( j=0;!f[j];j++);//找第一个非空子表
|
||||
r[0].next=f[j];//r[0].next指向第一个非空子表中第一个结点
|
||||
int t=e[j];
|
||||
while(j<RADIX)
|
||||
{
|
||||
for(j++;j<RADIX-1&&!f[j];j++);//找下一个非空子表
|
||||
if(f[j])
|
||||
{r[t].next=f[j];t=e[j];}//链接两个非空子表
|
||||
}
|
||||
r[t].next=0;//t指向最后一个非空子表中的左后一个结点
|
||||
}
|
||||
template<class type>
|
||||
void RadixSort(SLList<type> &SL)
|
||||
{//对L作基数排序,使得L按关键字自小到大有序
|
||||
for(int i=SL.keynum;i>=1;i--)//按最高位优先依次对各关键字进行分配和收集
|
||||
{
|
||||
Distrbute(SL.SList,i,f,e);//第i趟分配
|
||||
Collect(SL.SList,i,f,e);//第i趟收集
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user