#include <stdlib.h>
#include <stdio.h>
#define maxarray 10
typedef struct LNode //定义单链表节点
{
int data;
struct LNode * next;
}LNode,*Linklist;
/*---------------------------------------
函数名:ShellInsert
类型:void
功能:一趟增量为d的直接插入排序
过程:第i趟排序时,将arr[i]插入到已经有序增量为d的(arr[0]..arr[i-1])中
---------------------------------------*/
void ShellInsert(int arr[],int n,int d);
/*---------------------------------------
函数名:ShelllSort
类型:void
功能:希尔排序
过程:按数组d[dj]中元素为增量进行希尔排序
---------------------------------------*/
void ShellSort(int arr[],int n,int d[],int dj);
/*-----------------------------------------
函数类型:void
函数作用:将元素newdata从单链表尾插入至链表L
------------------------------------------*/
void RearInsert(Linklist &L,int newdata);
/*-----------------------------------------
函数类型:void
函数作用:输入数字至单链表L
------------------------------------------*/
void NumToLinklist(Linklist &L,int &dj);
/*-----------------------------------------
函数类型:void
函数作用:将单链表L中数据存入数组
------------------------------------------*/
void LinklistToArray(Linklist L,int d[]);
/*---------------------------------------
函数名:main
类型:void
功能:主函数
---------------------------------------*/
void main()
{
int array[maxarray];
cout<<"随机生成一个数组如下:"<<endl;
for(int i=0;i<maxarray;i++)
{
array[i]=rand()%100;
cout<<array[i]<<"\t";
}
cout<<"请输入希尔排序递减的间隔组合,例{5,3,2,1}、{6,3,1}..."<<endl;
int dj=0;
Linklist L=(Linklist)new(LNode);
L->next=NULL;
NumToLinklist(L,dj); //输入数字至单链表
int *d=new int[dj+1]; //声明间隔数组d[dj]
cout<<"(2)生成数组d["<<dj+1<<"],将单链表中数据存入数组:";
LinklistToArray(L,d); //将单链表中数据存入数组d[dj]
ShellSort(array,maxarray,d,dj+1); //希尔排序操作
cout<<"(3)经过希尔排序,即多趟间隔不同的直接插入排序后,数组如下:"<<endl;
for(i=0;i<maxarray;i++)
{
cout<<array[i]<<"\t";
}
cout<<endl;
}
/*---------------------------------------
函数名:ShellInsert的实现
---------------------------------------*/
void ShellInsert(int arr[],int n,int d)
{
for(int i=d;i<n;i++)
{
if(arr[i]<arr[i-d]) //当arr[i]比前面的有序(0..i-1)中最大的值小的时候,需要插入,否则i++,为了节省运算
{
int k=arr[i];
arr[i]=arr[i-d]; //先换一次
for(int j=i-2*d;arr[j]>k&&j>=0;j-=d) //找到空之前,所有元素后移
{
arr[j+d]=arr[j];
}
arr[j+d]=k; //插空
}
}
}
/*---------------------------------------
函数名:ShellSort的实现
---------------------------------------*/
void ShellSort(int arr[],int n,int d[],int dj)
{
for(int i=0;i<dj;i++)
{
ShellInsert(arr,n,d[i]);
}
}
/*---------------------------------------
函数名:NumToLinklist的实现
---------------------------------------*/
void NumToLinklist(Linklist &L,int &dj)
{
cout<<"请输入任意个数字,中间用空格隔开,连续两空格默认输入0,按回车结束:"<<endl;
cout<<"输入的间隔组合为:"<<endl;
char c;
int i=0,sum=0;dj=0;
while((c=getchar())!='\n')
{
i++;
if(c!=' ')
{
sum=(c-'0')+sum*10; //字符数字转整型数字
}
else
{
RearInsert(L,sum); //将输入的数字尾插入链表L中
dj++;
sum=0;
}
}
RearInsert(L,sum);
if(i==0)
cout<<"(1)未输入任何数字,链表为空"<<endl;
else
{
cout<<"(1)共输入了"<<dj+1<<"个数字,并将他们插入了单链表:";
for(Linklist p=L->next;p->next!=NULL;p=p->next) //链表循环输出
{
cout<<p->data<<"->";
}
cout<<p->data<<endl;
}
}
/*---------------------------------------
函数名:RearInsert的实现
---------------------------------------*/
void RearInsert(Linklist &L,int newdata)
{
Linklist p=L;
while(p->next!=NULL) //寻找尾节点
{
p=p->next;
}
Linklist k=(Linklist)new(LNode); //生成新节点
p->next=k; //尾插
k->next=NULL;
k->data=newdata;
}
/*---------------------------------------
函数名:LinklistToArray的实现
---------------------------------------*/
void LinklistToArray(Linklist L,int d[])
{
int i=0;
for(Linklist p=L->next;p->next!=NULL;p=p->next) //链表循环输出
{
d[i]=p->data;
i++;
}
d[i]=p->data;
for(int j=0;j<=i;j++) //数组循环输出
{
cout<<"d["<<j<<"]="<<d[j]<<" ";
}
cout<<endl;
}