实验名称 单链表的建立及其功能
- 实验内容、基本原理
- 实验内容
建立单链表,输入数据元素,对创建的单链表进行插入、删除数据元素、排序(根据字符对应的ASCII码进行由小到大)及退出功能。
2.基本原理
①创建
创立头结点,并令其指针指向NULL。构建函数,每加入一个新的数据元素,就建一个新的结点,令该结点的指针指向头结点指针所指位置,头结点指针指向该结点位置(头插法),结合循环语句,当输入为零的时候结束单链表的创建,这样就可以实现创建任意长度的单链表(在一定的范围内)。
②插入
构建函数,确定插入位置(由用户输入),结合循环语句和判断语句,如果位置超出单链表的长度,显示输出错误并返回循环,重新输入要插入的位置。创立新的结点并赋值,定义两个指针,借助循环使得一个指向定位好的结点的前一个结点,另一个指向创立的新结点。令新结点的指针指向定位好的结点的下一个结点,令定位好的结点的指针指向新的结点。
③删除
构建函数,确定删除位置(由用户输入)。定义两个指针,借助循环使一个指针指向目标结点,另一个指针指向其前置结点,令第二个指针所指结点的指针指向第一个指针所指结点的后置结点,释放第一个指针所指的结点。
④排序
此方法类似于冒泡排序法。构建函数,定义两个指针p,q,及一个整形指标变量t,为t赋值为1使得循环得以开始。t的作用:如果后续操作比较大小时有交换操作,则再进行外循环一次,直到后续比较大小无交换操作,即数据完成按从小到大顺序的排序操作。在外循环中,每次循环都使得q指向头结点,p指向第一个结点,t赋值为0以便排好顺序后停止循环。内循环里,从第一个结点开始,比较相邻的数据的大小,如需交换,则再次定义一个指针tmp,使其指向p指针指向的结点的指针指向的结点,此时三个指针分别指向三个相邻的结点。令q指向的结点的指针指向tmp指向的结点,p指向的结点的指针指向tmp指向的结点的指针,tmp指向的结点的指针指向p指向的结点,交换操作完成。为t赋值为1使得可以再进行一次外循环。内循环里,无论是否需要交换,都要将p、q指针移向下一个结点,以便后面的数据的大小判断。整个函数进行的操作:对单链表中数据进行多次扫描,第一次扫描会将含有最大数据的结点放在单链表最后,第二次扫描会将含有第二大数据的结点放在倒数第二的位置,以此类推。此算法和冒泡法不同的是,此算法在顺序正确的时候会直接退出循环,而冒泡法必须要进行特定步骤的循环次数;此算法在后面的扫描中,也会比较已经拍好顺序的数据,而冒泡法不会。
⑤退出
为循环设定条件,当输入指定字符(如‘q’或‘Q’)时退出循环。
3.实验步骤和结果
步骤
参考教材中的相应的内容(P25),首先建立单链表,其次编写主函数,引用创建的几个函数,结合循环语句和分支语句,实现相对应的功能。
结果
- 实验中出现的问题及解决方法
- 问题:程序较为复杂棘手,难以编写。
- 解决方法:与同学交流互助,完成程序。
- 实验总结及体会
该实验较为复杂,对于刚接触数据结构的我来说,可能有点复杂,需要初次建立单链表,还需要编写数个函数来实现单链表的多个功能。如此复杂的实验需要我们提前预习,上课认真听讲,课后好好巩固复习才能顺利完成。
- 附录
#include<stdio.h>
#include<malloc.h>
typedef char ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
void fun(LinkList head){
LNode *p=head->next,*q=head;
int t=1;
while(t){
p=head->next;
q=head;
t=0;
while(p&&p->next){
if(p->data>p->next->data){
LNode *tmp=p->next;
q->next=tmp;
p->next=tmp->next;
tmp->next=p;
t=1;
}
q=p;
p=p->next;
}
}
}
int ListInsert_L(LinkList head,int i,ElemType e){
LinkList p=head;
LinkList s;
int j;
for(j=1;j<i;j++){
if(p) p=p->next;
else break;
}
if(!p||i<1){
printf("error!!请输入正确的i值!!\n");
return 0;
}
s=(LinkList)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return 1;
}
LinkList CreateList_L(LinkList head){
ElemType temp;
LinkList p;
printf("请输入结点值(输入0结束):");
fflush(stdin);
scanf("%c",&temp);
while(temp!='0'){
if(('A'<=temp&&temp<='Z')||('a'<=temp&&temp<='z')){
p=(LinkList)malloc(sizeof(LNode));
p->data=temp;
p->next=head->next;
head->next=p;
}
printf("请输入结点值(输入0结束):");
fflush(stdin);
scanf("%c",&temp);
}
return head;
}
int ListDel_L(LinkList head,int i){
LinkList p,tmp;
int j;
p=head->next;
tmp=head;
for(j=1;j<i;j++){
if(p){
p=p->next;
tmp=tmp->next;
}
else break;
}
if(!p||i<1){
printf("error!!请输入正确的i值!!\n");
return 0;
}
tmp->next=p->next;
free(p);
return 1;
}
void ListPint_L(LinkList head){
LinkList p;
int i=0;
p=head->next;
while(p!=NULL){
i++;
printf("第%d个元素是:",i);
printf("%c\n",p->data);
p=p->next;
}
}
void main(){
int i;
char cmd,e;
LinkList head;
head=(LinkList)malloc(sizeof(LNode));
head->next=NULL;
CreateList_L(head);
ListPint_L(head);
do{
printf("i,I...插入\n");
printf("d,D...删除\n");
printf("q,Q...退出\n");
printf("o,O...排序\n");
do{
fflush(stdin);
scanf("%c",&cmd);
}while((cmd!='d')&&(cmd!='D')&&(cmd!='q')&&(cmd!='Q')&&(cmd!='i')&&(cmd!='I')&&(cmd!='o')&&(cmd!='O'));
switch(cmd){
case 'i':
case 'I':
printf("请输入你要插入的数据:");
fflush(stdin);
scanf("%c",&e);
printf("请输入你要插入的位置:");
scanf("%d",&i);
ListInsert_L(head,i,e);
ListPint_L(head);
break;
case 'd':
case 'D':
printf("请输入你要删除的元素的位置:");
fflush(stdin);
scanf("%d",&i);
ListDel_L(head,i);
ListPint_L(head);
break;
case 'o':
case 'O':
fun(head);
ListPint_L(head);
break;
}
}while((cmd!='q')&&(cmd!='Q'));
}