单链表实验报告.docx
《单链表实验报告.docx》由会员分享,可在线阅读,更多相关《单链表实验报告.docx(14页珍藏版)》请在冰豆网上搜索。
![单链表实验报告.docx](https://file1.bdocx.com/fileroot1/2022-11/15/79855d41-9417-460a-9fbe-52ece453c590/79855d41-9417-460a-9fbe-52ece453c5901.gif)
单链表实验报告
单链表练习实验
实验目的:
熟练掌握单的基本操作及简单应用。
实验内容:
⏹实验题目
1.书上习题2.6中的第5题。
(单链表的逆置)
2.书上习题2.6中第6题。
(删除已知值k的结点)
⏹程序代码
#include
#include
#include
typedefintELEMTYPE;
structnode{
ELEMTYPEelement;
structnode*next;
};
structnode*head;
structnode*tail;
voidinit()
{
head=(structnode*)malloc(sizeof(structnode));
if(!
head)exit(0);
head->next=NULL;
tail=head;
}
intisEmpty()
{
if(head==tail)return1;
elsereturn0;
}
intlength()
{
structnode*p;
intcnt=0;
for(p=head->next;p!
=NULL;p=p->next)
cnt++;
returncnt;
}
voidappend(ELEMTYPEitem)
{structnode*p;
p=(structnode*)malloc(sizeof(structnode));
if(!
p)exit(0);
p->element=item;
p->next=tail->next;
tail->next=p;
tail=p;
}
structnode*search(ELEMTYPEitem)
{
structnode*p;
p=head->next;
while(p!
=NULL)
{
if(p->element==item)
returnp;
else
p=p->next;
}
returnNULL;
}
voidinsert_x(ELEMTYPEx)//将元素x按序插入到单链表函数
{structnode*p,*q,*item;
item=(structnode*)malloc(sizeof(structnode));//创建结点
if(!
item)exit(0);
item->element=x;
p=head->next;
while(p)//从第一个结点开始比较与x的大小
{if(p->element>item->element)
{q=head;
while(q->next!
=p)//求前驱
q=q->next;
item->next=p;//实现插入操作
q->next=item;
break;}
elsep=p->next;}
if(!
p)//链表中元素都比较完毕后,实现将x插入到链表尾
{item->next=tail->next;
tail->next=item;
tail=item;
}
}
voidtraversal()
{
structnode*p;
printf("listis:
");p=head->next;
for(p=head->next;p!
=NULL;p=p->next)
printf("%d ",p->element);
printf("\n");
}
voidinvert()//逆置函数,借用老师课堂上的“头变尾,尾变头,中间结点指针方向逆置”
{structnode*p,*q,*k;//的思想。
先定义三个指针,分别依次指向第一第二第三个结点(头
p=head->next;q=p->next;k=q->next;//结点除外)处于第二位的指针指向第一位,然后三个
while(k)//指针逐次后移,直到k指针指向NULL;
{q->next=p;
p=q;///左边while循环就是该算法的实现代码
q=k;
k=q->next;
}
q->next=p;//实现完循环后,再进行最后结点的逆置
head->next->next=NULL;//将原来的第一个结点变为尾结点
head->next=q;//将头结点与原来的尾结点连接
}
intmain()
{
init();
append
(1);
append
(2);
append(3);
append(5);
append(6);
append(7);
printf("依次输出原有元素\n");
traversal();
insert_x(4);
printf("依次输出插入x后所有元素\n");
traversal();
invert();
printf("输出逆置后的元素\n");
traversal();
}
⏹关键部分加注释(见源代码注释)
⏹执行结果
⏹算法分析
⏹voidinvert()函数
q->next=p;
p=q;
q=k;
k=q->next;
上述四个语句为循环结构中的基本语句,设共有n个结点(头结点除外),则循环执行次数为
n—2,时间复杂度为o(n);
⏹voidinsert_x(ELEMTYPEx)函数
while(p)
{if(p->element>item->element)
{q=head;
while(q->next!
=p)
q=q->next;
上述即为循环结构语句,设共有n个结点
若比x值大的结点出现在第i个结点,则内循环需进行i—1次,则平均次数
n
1/n*∑(i—1)=(n—1)/2则f(n)=c1(n—1)*n/2+c2n+c3(c为常数);时间复杂度为o(n^2);
i=1
3.用单链表实现两个集合的合并。
#include
#include
#include
typedefintELEMTYPE;
structnode{
ELEMTYPEelement;
structnode*next;
};
voidinit(structnode*&head,structnode*&tail)
{
head=(structnode*)malloc(sizeof(structnode));
if(!
head)exit(0);
head->next=NULL;
tail=head;
}
intisEmpty(structnode*&head,structnode*&tail)
{
if(head==tail)return1;
elsereturn0;
}
intlength(structnode*&head,structnode*&tail)
{
structnode*p;
intcnt=0;
for(p=head->next;p!
=NULL;p=p->next)
cnt++;
returncnt;
}
voidappend(structnode*&head,structnode*&tail,ELEMTYPEitem)
{structnode*p;
p=(structnode*)malloc(sizeof(structnode));
if(!
p)exit(0);
p->element=item;
p->next=tail->next;
tail->next=p;
tail=p;
}
structnode*get(structnode*&head,structnode*&tail,inti)
{
structnode*p;
intj;
p=head->next;
for(j=1;(p!
=NULL)&&(j
p=p->next;
if((!
p)||(j>i))returnNULL;
returnp;
}
voidtraversal(structnode*&head,structnode*&tail)
{
structnode*p;
printf("listis:
");p=head->next;
for(p=head->next;p!
=NULL;p=p->next)
printf("%d ",p->element);
printf("\n");
}
intmain()//实现单链表局部化
{structnode*head1;structnode*tail1;//定义三个头和尾指针
structnode*head2;structnode*tail2;
structnode*head3;structnode*tail3;
head1=(structnode*)malloc(sizeof(structnode));//分别给六个指针分配六个指向的内存空间
tail1=(structnode*)malloc(sizeof(structnode));//防止野指针出现
head2=(structnode*)malloc(sizeof(structnode));
tail2=(structnode*)malloc(sizeof(structnode));
head3=(structnode*)malloc(sizeof(structnode));
tail3=(structnode*)malloc(sizeof(structnode));
init(head1,tail1);//初始化三个链表
init(head2,tail2);
init(head3,tail3);
append(head1,tail1,1);
append(head1,tail1,2);
append(head1,tail1,3);
append(head2,tail2,4);
append(head2,tail2,4);
append(head2,tail2,3);
append(head2,tail2,2);
printf("输出第一个链表的元素\n");
traversal(head1,tail1);
printf("输出第二个链表的元素\n");
traversal(head2,tail2);
inti;//利用循环实现将第一个链表追加到第三个链表后
for(i=1;i<=length(head1,tail1);i++)
append(head3,tail3,get(head1,tail1,i)->element);//利用get函数访问第一个链表中元素
for(i=1;i<=length(head2,tail2);i++)
append(head3,tail3,get(head2,tail2,i)->element);
printf("输出合并后的链表元素\n");
traversal(head3,tail3);
}
⏹关键部分加注释(见源代码注释)
⏹执行结果
⏹算法分析
for(i=1;i<=length(head1,tail1);i++)
append(