《数据结构和算法分析》课程设计顺序表单链表顺序栈查找排序算法.docx
《《数据结构和算法分析》课程设计顺序表单链表顺序栈查找排序算法.docx》由会员分享,可在线阅读,更多相关《《数据结构和算法分析》课程设计顺序表单链表顺序栈查找排序算法.docx(36页珍藏版)》请在冰豆网上搜索。
![《数据结构和算法分析》课程设计顺序表单链表顺序栈查找排序算法.docx](https://file1.bdocx.com/fileroot1/2023-1/2/c2fb8d66-9e2b-4c72-990b-53bd7ba3dd67/c2fb8d66-9e2b-4c72-990b-53bd7ba3dd671.gif)
《数据结构和算法分析》课程设计顺序表单链表顺序栈查找排序算法
*******大学
《数据结构与算法分析》课程设计
题目:
数据结构上机试题
学生姓名:
学号:
专业:
信息管理与信息系统
班级:
指导教师:
2014年04月
一、顺序表的操作
(1)插入元素操作:
将新元素x插入到顺序表a中第i个位置;
(2)删除元素操作:
删除顺序表a中第i个元素。
【插入操作原理】
线性表的插入操作是指在线性表的第i-1个数据元素和第i个数据元素之间插入一个新的数据元素,就是要是长度为n的线性表:
变成长度为n+1的线性表:
数据元素
和
之间的逻辑关系发生了变化。
(其【插入原理】在课本P23的算法2.3有解释)
【删除操作原理】
反之,线性表的删除操作是使长度为n的线性表:
变成长度为n-1的线性表:
数据元素
、
和
之间的逻辑关系发生变化,为了在存储结构上放映这个变化,同样需要移动元素。
(其【删除原理】在课本P24的算法2.4有解释)
【NO.1代码】
#include
#defineMAX100
typedefintdatatype;
typedefstruct
{
datatypedata[MAX];
intlist;
}
sequenlist;/*顺序表*/
intmain()
{
intinsert(sequenlist*L,intx,inti);
intdeletee(sequenlist*L,inti);
intinput(sequenlist*L);
intoutput(sequenlist*L);
sequenlists,*p=&s;
intindata,inlocate,deletedx;
input(p);
printf("请输入要插入的数:
");
scanf("%d",&indata);
printf("请输入要插入的位置:
");
scanf("%d",&inlocate);
insert(p,indata,inlocate);
printf("插入后的数据:
");
output(p);
printf("请输入要删除的位置:
");
scanf("%d",&deletedx);
deletee(p,deletedx);
printf("删除后的数据:
");
output(p);
return0;
}
intoutput(sequenlist*L)
{
inti;
for(i=0;i<=L->list;i++)
printf("%d",L->data[i]);
printf("\n\n");
return
(1);
}
intinput(sequenlist*L)
{
inti;
printf("请输入原始数据个数:
");
scanf("%d",&(L->list));
L->list--;
printf("请输入原始数据:
");
for(i=0;i<=L->list;i++)
scanf("%d",&(L->data[i]));
printf("原始数据为:
");
output(L);
return
(1);
}
intinsert(sequenlist*L,intx,inti)
{
intj;
if(((*L).list)>=MAX-1)
{
printf("overflow");return0;
}
else
{
if((i<1)||(i>((*L).list)+1))
{
printf("error\n");
return0;}
else
{
for(j=L->list;j>=i-1;j--)
L->data[j+1]=L->data[j];L->data[i-1]=x;L->list++;
}
}
return
(1);
}
intdeletee(sequenlist*L,inti)/*定义删除函数*/
{
intj;
if((i<1)||(i>(L->list)+1))
{
printf("error\n");
return0;
}
else
{
for(j=i;j<=L->list;j++)
L->data[j-1]=L->data[j];
L->list--;
}
return
(1);
}
【运行截图演示】
①、如下面的运行截图所示,当输入的线性表长度设置为12的时候,该线性表最多能输入12位数的长度。
输入要插入的数和插入数的位置下标,便可以进行插入操作;同理当输入要执行删除操作数的位置下标,可以将该数删除出线性表。
②、如下面的运行截图所示,当初始设置的线性表长度为5的时候,其5个数分别是-3、4、5、0、1。
若是要执行程序中输入的插入数字“2”,其插入数的位置在“-4”的时候,程序是不能执行插入操作的。
此时的线性表能插入的下标范围为“1——5”,明显“-4”数值<下限“1”数值,所以程序执行“error”。
③、如下面的运行截图所示,同理该线性表要插入数的位置“6”数值>上限“5”数值,所以程序执行“error”。
④、如下面的运行截图所示,初始设置的线性表插入数字2之后,要删除位置7已超过线性表的最大长度n=6,所以程序执行“error”。
⑤、如下面的运行截图所示,同理该线性表要删除数的位置“0”下标不存在,所以程序执行“error”。
二、单链表的操作
(1)创建一个带头结点的单链表;
(2)插入元素操作:
将新元素x插入到单链表中第i个元素之后;
(3)删除元素操作:
删除单链表中值为x的元素。
【创建操作原理】
在单链表的第一个结点之前附设一个结点,称之为头结点。
头结点的数据域可以不存储任何信息,也可以存储线性表的长度等的附加信息,头结点的指针域存储指向第一个结点的指针(即第一个元素结点的存储位置)。
【插入操作原理】
为插入数据元素x,首先要生成一个数据域为x的结点,然后插入在单链表中。
根据插入操作的逻辑定义,还需要修改结点a中的指针域,令其指向结点x,而结点x中的指针域应指向结点b,从而实现3个元素a、b和x之间逻辑关系的变化。
假设s为指向结点x的指针,则上述指针修改用语描述即为:
【删除操作原理】
反之,在线性表中删除元素b时,为在单链表中实现元素a、b和c之间逻辑关系的变化,仅需要修改结点a中的指针域即可。
假设p为指向结点a的指针,则上述指针修改用语描述即为:
【NO.2代码】
#include
#include
typedefstructnode//定义链表
{
intdata;
structnode*next;
}
snode;
snode*creat()//创建链表的函数
{
snode*head,*p,*q;
head=(snode*)malloc(sizeof(snode));
p=head;
intx;
printf("请输入创建链表的值,用“0”结束输入。
\n");
printf("x=");
scanf("%d",&x);
while(x!
=0)
{
q=(snode*)malloc(sizeof(snode));
q->data=x;
p->next=q;
p=q;
printf("x=");
scanf("%d",&x);
}
p->next=NULL;
returnhead;
}
intlength(snode*head)//测链表的结点数
{
inti=0;
snode*p=head->next;
while(p!
=NULL)
{
p=p->next;
i++;
}
returni;
}
voiddisplay(snode*head)
{
snode*p=head->next;
for(inti=0;i{
printf("%4d",p->data);
p=p->next;
}
printf("");
}
intlocate(snode*head,intx)
{
snode*p=head->next;
inti=1;
while(p!
=NULL&&x!
=p->data)
{
p=p->next;
i++;
}
if(p==NULL)
return0;
else
returni;
}
intinsnode(snode*head,intx,inti)//把x插入到链表的第i的位置
{
intj;
snode*p=head->next,*s;
if(i<1||i>(length(head)+1))
return0;
elseif(i==1)
{
s=(snode*)malloc(sizeof(snode));
s->next=p;
head->next=s;
s->data=x;
}
else
{
for(j=1;jp=p->next;
s=(snode*)malloc(sizeof(snode));
s->next=p->next;
p->next=s;
s->data=x;
}
return1;
}
intdelnode(snode*head,inti)//删除链表中第i个结点
{
snode*p=head->next,*q=head;
if(i<1||i>length(head))
return0;
elseif(i==1)
{
head->next=p->next;
free(p);
}
else
{
for(intj=1;j
{
p=p->next;q=q->next;
}
q->next=p->next;
free(p);
}
return1;
}
voidsort(snode*head)//把链表中每个结点的值按从小到大排列
{
snode*p,*q;
intk;
for(p=head->next;p!
=NULL;p=p->next)
for(q=p->next;q!
=NULL;q=q->next)
if(p->data>q->data)
{
k=p->data;
p->data=q->data;
q->data=k;
}
}
voidinsert(snode*head,intx)//在有序链表中插入x,插入后仍保持有序
{
snode*p=head->next,*s,*q=head;
while(p!
=NULL&&p->data{
q=q->next;
p=p->next;
}
s=(snode*)malloc(sizeof(snode));
s->next=q->next;
s->data=x;
q->next=s;
}
voiddel_min_max(snode*head,intmin,intmax)//删除有序链表中值min到值max中的结点
{
snode*p=head->next,*q=head;
while(p!
=NULL&&p->data<=min)
{
q=p;
p=p->next;
}
while(p!
=NULL&&p->data{
q->next=p->next;
free(p);
p=q->next;
}
}
voiddel_min(snode*head)
{
snode*p=head->next,*q=head;
snode*p_min,*q_min;
p_min=p;
q_min=q;
while(p!
=NULL)
{
q=p;p=p->next;
if(p!
=NULL&&p->datadata)
{
q_min=p_min;
p_min=p;
}
}
q_min->next=p_min->next;
free(p_min);
}
intmain()
{
intmin,max;
snode*headl=creat();//创建链表
printf("最初的链表如下:
");
display(headl);
printf("\n\n");
intnum,location;
printf("请输入您要查找的数:
");
scanf("%d",&num);
if(locate(headl,num))
printf("数字%d在链表中的位置为:
%d\n\n",num,locate(headl,num));
else
printf("数字%d在链表中不存在!
\n\n",num);
printf("请分别输入您要插入到链表中的数以及想插入的位置(用空格号间隔开):
");
scanf("%d%d",&num,&location);
if(insnode(headl,num,location))
{
printf("插入新值以后的链表如下:
");
display(headl);
printf("\n\n");
}
elseprintf("输入有误!
\n\n");
printf("请输入您想删除的结点位置:
");
scanf("%d",&location);
if(delnode(headl,location))
{
printf("删除第%d个结点后的链表如下:
",location);
display(headl);
printf("\n\n");
}
else
printf("输入有误!
\n\n");
}
【运行截图演示】
①、如下面的运行截图所示,创建带有头结点且长度为8的单链表:
4、8、2、-4、-6、1、9、-1。
输入要查询的数“-6”,则查询到单链表中数“-6”的存储位置为“5”的下标号。
输入要插入的数和插入数的位置下标,便可以进行插入操作。
程序中要求插入的数是“3”,插入数的位置下标为“5”,两者之间用空格号隔开,则插入后的新单链表为:
4、8、2、-4、3、-6、1、9、-1。
同理当输入要执行删除操作的数位置下标,可以对该数删除出线性表。
程序中要求删除的数下标是7,则执行该删除操作之后的新单链表为:
4、8、2、-4、3、-6、9、-1。
②、如下面的运行截图所示,创建带有头结点且长度为8的单链表,要查询的数“3”不在该单链表中,所以程序执行“error”。
③、如下面的运行截图所示,创建带头结点且长度为8的单链表,要插入数的位置下标“-1”不在该单链表中,所以程序执行“error”。
④、如下面的运行截图所示,创建带头结点且长度为8的单链表,要插入的位置下标“9”为单链表最大长度,所以程序执行插入操作。
⑤、如下面的运行截图所示,创建带头结点且长度为8的单链表,要插入的位置下标“10”超出单链表长度,所以程序不执行插入操作。
⑥、如下面的运行截图所示,创建带头结点且长度为8的单链表,要删除数的位置下标“-2”不在该单链表中,所以程序执行“error”。
⑦、如下面的运行截图所示,创建带头结点且长度为8的单链表,要删除数的位置下标“10”超出单链表长度,所以程序执行“error”。
三、顺序栈的操作
在顺序栈上实现将非负十进制数转换成二进制数。
【数值转换原理】
十进制数N和其他d进制数的转换时计算机实现计算的基本问题,其解决方法很多,其中一个简单算法基于下列原理:
(其中:
div为整除运算,mod为求余运算)
假设现在要编制一个满足下列要求的程序:
对于输入的任意一个非负十进制整数,打印输出与其等值的二进制数。
由于上述计算过程是从低位到高位顺序产生二进制数的各个数位,而打印输出,一般来说应从高位到低位进行,恰好和计算过程相反。
因此,若将计算过程中得到的二进制数的各位顺序进栈,则按出栈序列打印输出的即为输入对应的二进制数。
(其【数值转换】在课本P48的算法3.2有解释)
【NO.3代码】
#include
#include
#defineMaxSize50
typedefcharElemType;
chardigit[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
typedefstruct
{
ElemTypedata[MaxSize];
inttop;
}
SqStack;
voidInitStack(SqStack*&s)
{
s=(SqStack*)malloc(sizeof(SqStack));
s->top=-1;
}
intPush(SqStack*&s,ElemTypee)
{
if(s->top==MaxSize-1)
return0;
s->top++;
s->data[s->top]=e;
return1;
}
intPop(SqStack*&s,ElemType&e)
{
if(s->top==-1)
return0;
e=s->data[s->top];
s->top--;return1;
}
intGetTop(SqStack*s,ElemType&e)
{
if(s->top==-1)
return0;
e=s->data[s->top];
return1;
}
voidDispStack(SqStack*s)
{
inti;
for(i=s->top;i>=0;i--)
printf("%c",s->data[i]);
printf("\n");
}
intfun(SqStack*s,intnum,intk)//可将十进制转换成任意进制
{
staticintcount=0;
intn;
if(num{
Push(s,digit[num]);
returncount;
}
n=num%k;
Push(s,digit[n]);
fun(s,num/k,k);
}
intmain()
{
SqStack*t;
inti;
InitStack(t);
printf("请输入一个非负十进制数:
");
scanf("%d",&i);
fun(t,i,2);
printf("其二进制数为:
");
DispStack(t);
free(t);
return0;
}
【运行截图演示】
①、如下面的运行截图所示,输入非负十进制整数“14”,经过数值转换之后的二进制数为“1110”。
②、如下面的运行截图所示,输入十进制整数“-2”,由于“-2”为负数,所以无法经过数值转换为二进制数。
③、如下面的运行截图所示,输入非负十进制整数“0”,经过数值转换之后的二进制数为“0”。
四、查找算法
在顺序表中采用顺序查找算法和折半查找算法寻找关键字X在顺序表中的位置。
【顺序查找原理】
从表中最后一个记录开始,逐个进行记录的关键字和给定值的比较,若某个记录的关键字和给定值比较相等,则查找成功,找到所查记录;反之,若直至第一个记录,其关键字和给定值比较都不等,则表明表中没有所查记录,查找不成功。
在等概率情况下顺序查找的平均长度为:
【折半查找原理】
先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。
折半查找过程是以处于区间中间位置记录的关键字和给定值比较,若相等,则查找成功,若不等,则缩小范围,直至新的区间中间位置记录的关键字等于给定值或者查找区间的大小小于零时(表明查找不成功)为止。
假设表中每个记录的查找概率相等
,则查找成功时折半查找的平均查找长度:
【NO.4代码】
#include
#include
#defineMAXL1000
#defineINF32767
intprocess[MAXL],pn;
//顺序表的存储结构
typedefintKeyType;
typedefintInfoType;
typedefstruct
{
KeyTypekey;
InfoTypedata;
}
NodeType;
typedefNodeTypeSeqList[MAXL];
//索引表的存储结构
typedefstruct
{
KeyTypekey;
intlink;
}
IdxType;
typedefIdxTypeIDX[MAXL];
//顺序查找算法
intSeqSearch(SeqListR,intn,KeyTypek)
{
inti=0;
pn=0;
while(i=k)
{
process[pn++]=R[i].key;
i++;
}
if(i>=n)return-1;
elsereturni;
}
//折半查找算法
intBinSearc