数据结构
实验 链表的实现和应用
一、实验目的
1、熟练掌握线性表的链式存储结构的设计及其基本操作的实现。
二、实验原理
1、线性表的链式存储结构及其应用。
三、实验设备
Win系统电脑一台
四、实验过程(程序清单)
#include<stdio.h>
#include<stdlib.h>
#define ElemType char
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
//1.头插入法建立不带头结点的单链表
void creatlink_nohead_head(LinkList &head){
LinkList t;
char ch;
printf("单链表元素值为单个字符,连续输入,$为结束字符:");
while((ch=getchar())!='$'){
t=(LinkList) malloc(sizeof(LNode));
t->data =ch;
t->next =head;
head=t;
}
}
//2.头插入法建立带头结点的单链表
void creatlink_head_head(LinkList &head){
LinkList t;
char ch;
t=(LinkList) malloc(sizeof(LNode));
head=t;
t->next =NULL;
printf("单链表元素值为单个字符,连续输入,$为结束字符:");
while((ch=getchar())!='$'){
t=(LinkList ) malloc(sizeof(LNode));
t->data =ch;
t->next=head->next;
head->next=t;
}
}
void creatlink_nohead_rail(LinkList &head){
//3.用尾插入法建立不带头结点的单链表
LinkList last,t;
char ch;
last=head;
printf("单链表元素值为单个字符,连续输入,$为结束字符:");
while((ch=getchar())!='$'){
t=(LinkList )malloc(sizeof(LNode));
t->data=ch;
t->next=NULL;
if(head==NULL){
head=t;last=t;
}
else{
last->next=t;
last=t;
}
}
}
//4.用尾插入法建立带头结点的单链表
void creatlink_head_rail(LinkList &head){
LinkList last,t;
char ch;
t=(LinkList)malloc(sizeof(LNode));
head=t;
last=t;
t->next=NULL;
printf("单链表元素值为单个字符,连续输入,$为结束字符:");
while ((ch=getchar())!='$'){
t=(LinkList)malloc(sizeof(LNode));
t->data =ch;
t->next =NULL;
last->next =t;
last=t;
}
}
void InvertLinkList(LinkList &L){
//5.逆置单链表 ,L为头指针单链表
LinkList p,s;
p=L;L=NULL; //设逆置后的链表为空表
while(p){
s=p;p=p->next;//删除p所指链表中的一个节点s
s->next=L;L=s;//将s节点插入到逆置表头
}
}
void creatlink_order_head(LinkList &head){
//6、7、9等功能实现的前提:建立带头结点的有序单链表
LinkList t,p,q;
char ch;
t=(LinkList )malloc(sizeof(LNode));
head=t;
t->next=NULL;
printf("单链表元素值为单个字符,连续输入,$为结束字符:");
while((ch=getchar())!='$'){
t=(LinkList )malloc(sizeof(LNode));
t->data=ch;
q=head;p=head->next;
while(p!=NULL && p->data<=ch){
q=p;p=p->next;
q->next=t;t->next=p;
}
}
}
void inser_order(ElemType x,LinkList head){
//6.有序表中插入元素x,并保持表有序
LinkList pr,pn,pp;
pr=head;pn=head->next;
while(pn!=NULL && pn->data<x){
pr=pn;
pn=pn->next;
}
pp=(LinkList)malloc(sizeof(LNode));
pp->data=x;
pp->next=pr->next;
pr->next=pp;
}
void deletex(LinkList a){
//7.有序链表中删除重复元素,重复元素保留一个
LinkList la;
la=a->next;
while(la!=NULL && la->next!=NULL){
if(la->data==la->next->data){
la->next=la->next->next;
}
else la=la->next;
}
}
void delete1(LinkList a){
//8.无序链表中删除重复元素,重复元素保留一个
LinkList r,p,q;
r=a->next;
while(r!=NULL){
p=r->next;q=r;
while(p!=NULL){
if(p->data==r->data){
q->next=p->next;p=p->next;
}
else{
q=p;p=p->next;
}
}
r=r->next;
}
}
void unite(LinkList a,LinkList b,LinkList c){
//a,b为两有序链表,合并到c表,并保持有序
LinkList la,lb,lc,p;
la=a->next;lb=b->next;lc=c;
while(la!=NULL && lb!=NULL){
if(la->data<=lb->data){
p=(LinkList)malloc(sizeof(LNode));
p->data=la->data;p->next=NULL;
lc->next=p;lc=lc->next;la=la->next;
}
else {
p=(LinkList)malloc(sizeof(LNode));
p->data=lb->data;p->next=NULL;
lc->next=p;lc=lc->next;lb=lb->next;
}
}
while(la!=NULL){
p=(LinkList)malloc(sizeof(LNode));
p->data=la->data;p->next=NULL;
lc->next=p;lc=lc->next;la=la->next;
}
while(lb!=NULL){
p=(LinkList)malloc(sizeof(LNode));
p->data=lb->data;p->next=NULL;
lc->next=p;lc=lc->next;lb=lb->next;
}
}
int locate(LinkList &a,ElemType x){
//检查元素x是否在a表中,为功能10做准备
LinkList la=NULL;
la=a->next;
while(la!=NULL){
if(la->data==x){
return 1;
}
else la=la->next;
}
return 0;
}
//将x元素加入a表中,为功能10做准备
void insert(LinkList a,ElemType x){
LinkList p,q;
p=(LinkList)malloc(sizeof(LNode));
p->data =x;
for(q=a;q->next ;q=q->next );
p->next=q->next ;
q->next=p;
}
//10.两个链表去重后合并
void unionn(LinkList a1,LinkList b1){
LinkList lb;
lb=b1->next;
while(lb!=NULL){
if(!locate(a1,lb->data ))
insert(a1,lb->data );
lb=lb->next ;
}
}
//输入不带头结点的单链表;输出->单链表元素值并计数
int count_nohead(LinkList head){
int i=0;
LinkList p;
p=head;
printf("输出单链表元素值:");
while(p!=NULL){
printf(" %c",p->data);
i++;
p=p->next;
}
printf("\n");
return i;
}
//带头结点的单链表:输出单链表元素值并计数
int count_head(LinkList head){
int i=0;
LinkList p;
p=head->next ;
printf("输出单链表的元素值:");
while(p!=NULL){
printf(" %c",p->data );
i++;
p=p->next ;
}
printf("\n");
return i;
}
void ifinsert(ElemType x,ElemType a,LinkList head){
LinkList p,t;
int flag=1;
t=(LinkList)malloc(sizeof(LNode));
t->data =x;
p=head;
while(p->next !=NULL&&flag){
if(p->data==a){
t->next =p->next ;
p->next =t;
flag=0;
}
else
p=p->next ;
}
if(flag){
p->next=t;
t->next =NULL;
}
}
//输出
void print(LinkList head){
LinkList p;
p=head;
while(p!=NULL){
printf(" %c",p->data );
p=p->next;
}
}
int main(){
LinkList head,a1,a2,c;
int num=0,loop,j;
//char *p;
ElemType ch,ch2;
loop=1;
while(loop){
printf(" 1 -- 建立单链表(头插入,不带头结点)\n");
printf(" 2 -- 建立单链表(头插入,带头结点)\n");
printf(" 3 -- 建立单链表(尾插入,不带头结点)\n");
printf(" 4 -- 建立单链表(尾插入,带头结点)\n");
printf(" 5 -- 逆置单链表\n");
printf(" 6 -- 有序链表插入\n");
printf(" 7 -- 有序链表删除重复元素\n");
printf(" 8 -- 无序链表删除重复元素\n");
printf(" 9 -- 两链表合并并排序\n");
printf(" 10 -- 两集合的并集(用链表实现)\n");
printf(" 11 -- x节点插到与a值相等的节点之后\n\n");
printf("请选择项号 : ");
scanf("%d",&j);
/*fflush(stdin);*/
printf("\n\n");
if(j>=1 && j<=11)
switch(j) {
case 1: printf("\n 建立单链表\n\n");
head=NULL;
creatlink_nohead_head(head);//头插入,不带头结点;
print(head);
//fflush(stdin); //功能是清空输入缓冲区,通常是为了确保不影响后面的数据读取
num=count_nohead(head);
printf("单链表元素个数=%d\n",num-1);
break;
case 2:printf("\n 建立单链表\n\n");
head=NULL;
creatlink_head_head(head);//头插入,带头结点
print(head);
//fflush(stdin);
num=count_head(head);
// print(head);
printf("单链表元素个数 = %d\n",num-1);
break;
case 3:printf("\n 建立单链表\n\n");
head=NULL;
creatlink_nohead_rail(head);//尾插入。不带头结点
print(head);
//fflush(stdin);
num=count_nohead(head);
printf("单链表元素个数 = %d\n",num-1);
break;
case 4:printf("\n 建立单链表\n\n");
head=NULL;
creatlink_head_rail(head);//尾插入法建立带头结点的单链表
print(head);
//fflush(stdin);
num=count_head(head);
printf("单链表元素个数 = %d\n",num-1);
break;
case 5: printf("\n 建立单链表\n\n");
head=NULL;
creatlink_nohead_rail(head);//尾插入,不带头结点
//fflush(stdin);
num=count_nohead(head);
printf("单链表元素个数 = %d\n",num-1);
printf("\n 逆置单链表\n\n");
InvertLinkList(head);
num=count_nohead(head);
break;
case 6:printf("\n 建立单链表\n\n");
head=NULL;
creatlink_head_head(head);//建立带头结点的有序单链表
//fflush(stdin);
num=count_head(head);
printf("单链表元素个数 = %d\n",num-1);
printf("\n输入插入元素值:");
getchar();ch=getchar();
inser_order(ch,head);
printf("\n 元素插入后\n\n");
num=count_head(head);
printf("单链表元素个数 = %d\n",num-1);
break;
case 7:printf("\n 建立单链表\n\n");
head=NULL;
creatlink_head_head(head);//建立带头结点的有序单链表
//fflush(stdin);
num=count_head(head);
printf("\n 删除重复元素后\n\n");
deletex(head);
num=count_head(head);
break;
case 8:printf("\n 建立单链表\n\n");
head=NULL;
creatlink_head_rail(head);//尾插入法建立带头结点的单链表
//fflush(stdin);
num=count_head(head);
printf("单链表元素个数 = %d\n",num-1);
printf("\n 删除重复元素后\n\n");
delete1(head);
num=count_head(head);
break;
case 9:printf("\n 建立单链表a1\n\n");
a1=NULL;
creatlink_head_head(a1);//建立带头结点的有序单链表
//fflush(stdin);
num=count_head(a1);
printf("单链表a1元素个数 = %d\n",num-1);
printf("\n 建立单链表a2\n\n");
a2=NULL;
creatlink_head_head(a2);//建立带头结点的有序单链表
//fflush(stdin);
num=count_head(a2);
printf("单链表a2元素个数 = %d\n",num-1);
c=NULL;
c=(LinkList)malloc(sizeof(LNode));
c->next=NULL;
unite(a1,a2,c);
num=count_head(c);
printf("合并到单链表c中,元素个数=%d\n",num-2);
break;
case 10:printf("\n 建立单链表a1\n\n");
a1=NULL;
creatlink_head_rail(a1);//尾插入法建立带头结点的单链表
//fflush(stdin);
num=count_head(a1);
printf("\n 建立单链表a2\n\n");
a2=NULL;
creatlink_head_rail(a2);//尾插入法建立带头结点的单链表
//fflush(stdin);
num=count_head(a2);
printf("\n\n 两链表并集运算,结果保留在a1中\n\n");
unionn(a1,a2);
num=count_head(a1);
break;
case 11:printf("\n 建立单链表\n\n");
head=NULL;
creatlink_nohead_rail(head);//尾插入,不带头节点
//fflush(stdin);
num=count_nohead(head);
printf("单链表元素个数 = %d\n",num-1);
printf("\n输入要插入的元素值(x值):");
getchar();ch=getchar();
printf("\n输入要插入的到哪个字符的后面(a值):");
getchar();ch2=getchar();
ifinsert(ch,ch2,head);
printf("\n输出:");
print(head);
break;
}
printf("结束此练习吗? (0 -- 结束 1 -- 继续) : ");
scanf("%d",&loop);
printf("\n");
}
}
五、实验结果
六、实验心得
1、掌握线性表的链式存储结构及其基本操作。
2、根据编译器报错的提示修改代码。
3、规范代码格式。