大学实验3指导:利用单链表实现A-B

实验目的:深入理解单链表的建立及操作

实验内容:

1.建立单链表AB

2.实现主要的函数,查找、插入、删除等

3.实现操作A-B

 

步骤1:包含必要的函数库,对结构体LNode中的抽象数据类型ElemType进行具体定义

1 #include <stdio.h>
2 
3 #include <stdlib.h>
4 
5 typedef int ElemType;

步骤2:定义结构体LNode

1 typedef struct LNode
2 
3 {
4 
5      ElemType data;
6 
7      struct LNode *next;
8 
9 }LNode, *LinkList;

F提示LNode用于声明单链表中的一个数据结点,LinkList用于声明指向单链表中的数据结点的指针

步骤3:定义基本的函数InitList_L()ListInsert_L()GetElem_L ()ListSize_L(),用于建立单链表AB

步骤3.1实现函数InitList_L()。(该函数用于对单链表进行初始化,即创建头结点)

F提示1:参数L为指向“单链表头指针”的指针,即

LinkList *L;

等价于

LNode **L;

F提示2:由于需要在函数中修改L所指向的头指针的内容(即调用InitList_L()之前,头指针为空,调用InitList_L()之后,头指针指向新创建的头结点),因此需要在L前加“*”号。

F提示3:由于*L表示头指针的内容,因此在修改头结点的next域时,可以执行:

(*L)->next=NULL

由于在a为指向结构体的指针时,运算a->b等价于(*a).b,因此该语句等价于:

(*(*L)).next=NULL;

 

 1 void InitList_L(LinkList *L)
 2 
 3 {
 4 
 5      *L=(LinkList)malloc(sizeof(LNode));
 6 
 7      if (*L==NULL)
 8 
 9          exit(-1);
10 
11      (*L)->next=NULL;
12 
13      //等价于(*(*L)).next=NULL;                                              
14 
15 }

步骤3.2实现函数ListInsert_L ()。(在指定位置上插入新元素)

 1 int ListInsert_L(LinkList L,int i,ElemType e)
 2 
 3 { 
 4     LNode *p,*s;
 5     int j;
 6     p=L;
 7     j=0;
 8     while(p&&j<i-1)
 9     {
10         p=p->next;++j;
11     }
12     if(!p||j>i-1) 
13         return 0;
14      s=(LinkList)malloc(sizeof(LNode));
15      s->data=e;
16      s->next=p->next;
17      p->next=s;
18      return 1;
19  }

步骤3.3GetElem_L()。(返回顺序表中指定位置上的元素)

 1 int GetElem_L(LinkList L, int i, ElemType *e)
 2 {
 3     LinkList p;
 4     int j=1;
 5     p=L->next;
 6     while(p&&j<i)
 7     {
 8         p=p->next; 
 9         ++j;
10     }
11     if(!p||j>i) 4
12         return 0;
13     *e=p->data;
14     return 1;  
15 }

步骤3.4ListSize_L()。(返回单链表的长度)

 

 1 int ListSize_L(LinkList L)
 2 {
 3     LNode *p;
 4     int count=0;
 5     p=L;
 6     while(p->next!=NULL)
 7     {
 8         p=p->next;
 9         count++;
10     }
11     return count;  
12 }

 

 

步骤4:建立线性表AB,并输出其中的元素

F提示:采用静态方式创建A=(3,5,8,11)B=(2,6,8,9,11,15,20)

 1 int main()
 2 {
 3     int i,flag,e;
 4     //定义两个头指针
 5     LinkList A,B;
 6     //测试函数GetElemPointer_L()
 7     LNode *p;
 8     /*初始化单链表A,将头指针A的地址(即指向A的指针)传入*/
 9     InitList_L(&A);
10     /*初始化单链表B,将头指针B的地址(即指向B的指针)传入*/ 
11     InitList_L(&B);
12     /*为单链表A填充数据*/
13     ListInsert_L(A,1,3);
14 15     ListInsert_L(A,4,11);
16     /*为单链表B填充数据*/
17     ListInsert_L(B,1,2);
18 19     ListInsert_L(B,7,20);
20     /*输出单链表A*/
21     printf("单链表A中的元素为:
"); 
22     for(i=1;i<=ListSize_L(A);i++)
23     {
24         flag=GetElem_L(A,i,&e);
25         if(flag)
26             printf("%4d",e);
27     }
28     printf("
");
29     /*输出单链表B*/
30     printf("单链表B中的元素为:
"); 
31     for(i=1;i<=ListSize_L(B);i++)
32     {
33         flag=GetElem_L(B,i,&e);
34         if(flag)
35         printf("%4d",e);
36     }
37     printf("
");
38 }

步骤4的输出结果

 

步骤5:实现函数ListDelete_L()。(用于删除指定位置上的元素)

F提示:该函数的声明为:

1 int ListDelete_L(LinkList *L,int i, ElemType *e)

步骤6:测试函数ListDelete_L()

 1     flag=ListDelete_L(&B,7,&e);
 2     if(flag)
 3     printf("被删除的元素为:%4d",e);
 4     printf("
");
 5     printf("单链表B中的剩余元素为:
"); 
 6     for(i=1;i<=ListSize_L(B);i++)
 7     {
 8         flag=GetElem_L(B,i,&e);
 9         if(flag)
10         printf("%4d",e);
11     }
12     printf("
");


步骤6的输出结果

步骤7:实现函数LocateElem_L ()

LocateElem_L():返回给定元素在单链表中的位置(序号)。注意:头结点的序号为0

F提示:首先,令p指向单链表的表头结点,即L->next。若单链表为空,即L->next==NULL,则返回0。否则,对单链表进行遍历,并返回匹配结点的位置。最后,若最终没有找到,则返回0

该函数声明为:

1 int LocateElem_L(LinkList L, ElemType e);

步骤8:测试函数LocateElem_L()

1 flag=LocateElem_L(B,15);
2 printf("元素15在单链表B中的位置为:%4d
",flag); 


步骤8的输出结果

步骤9:实现函数GetElemPointer_L()。(返回指向单链表中第i个元素的指针)

F提示:首先,若单链表为空,即L->next==NULL,则返回空指针。接下来,若参数i非法,则返回空指针。然后,对单链表进行遍历,并返回匹配结点的指针。最后,若最终没有找到,则返回空指针。

该函数声明为:

1 LNode *GetElemPointer_L(LinkList L,int i);

步骤10:测试函数GetElemPointer_L()

1 p=GetElemPointer_L(A,3);
2 printf("单链表A中的第3个元素为:%4d
",p->data);

步骤10的输出结果

步骤11:实现函数DelElem_L()(实现A-B)。

F提示:利用循环遍历顺序表B。在每轮循环中,先利用函数GetElemPointer_L()取得指向B中的当前结点的指针(假设该结点指针保存在p中),再利用函数LocateElem_L()检查中A是否存在数据域等于p->data的结点,若存在则返回匹配结点的位置pos。最后,利用函数ListDelete_L()删除所匹配的结点(即A中的第pos个结点)。

函数DelElem_L()的声明如下:

1 void DelElem_L(LinkList A,LinkList B);

步骤12:测试函数DelElem_L()的功能

  

1     DelElem_L(A,B);//执行A-B
2     printf("单链表A中的剩余元素为:
"); 
3     for(i=1;i<=ListSize_L(A);i++)
4     {
5         flag=GetElem_L(A,i,&e);
6         if(flag)
7         printf("%4d",e);
8     }
9     printf("
");


步骤12的输出结果

思考题

1.将有关单链表的所有基本函数组织成单独的文件“LinkList.h”,然后利用include命令调用该文件。

 1 /*删除指定位置上的元素*/
 2 int ListDelete_L(LinkList *L,int i, ElemType *e) {
 3     LNode *p,*q;
 4     p=*L;
 5     int j=0;
 6     while(p->next&&j<i-1) {
 7         p=p->next;
 8         ++j;
 9     }
10     if(!(p->next)||j>i-1) return 0;
11     q=p->next;
12     p->next=q->next;
13     *e=q->data;
14     free(q);
15     return 1;
16 }
17 
18 /*返回给定元素在单链表中的位置*/
19 int LocateElem_L(LinkList L, ElemType e) {
20     LNode *p;
21     int i;
22     if(L->next==NULL)
23         return 0;
24     p=L->next;
25     i=1;
26     while(p) {
27 
28         if(p->data==e)
29             return i;
30         else {
31             p=p->next;
32             i++;
33         }
34         if(!p) return 0;
35     }
36 }
37 
38 /*返回指向单链表中第i个元素的指针*/
39 /*若找到第i个结点,则返回指向该结点的指针;否则,返回空指针*/
40 LNode *GetElemPointer_L(LinkList L,int i) {
41     LNode *p;
42     int j;
43 //若单链表为空
44     if(L->next==NULL)
45         return NULL;
46 //若参数非法
47     if(i<1)
48         return NULL;
49     p=L;
50     j=0;
51     while(p->next!=NULL&&j<i) {
52         p=p->next;
53         j++;
54     }
55     if(j==i)
56         return p;
57     else
58         return NULL;
59 }
60 
61 void DelElem_L(LinkList A,LinkList B) {
62     int i,pos,flag;
63     ElemType e;
64     LNode *p;
65     for(i=1; i<=ListSize_L(B); i++) {
66         p=GetElemPointer_L(B,i);//p指向单链表B中存在第i个结点
67         if(p) { //若单链表B中存在第i个结点
68             pos=LocateElem_L(A,p->data);//若A中存在相同的结点,则用返回其在A中的位置
69             if(pos>0)//若存在,则在A中删除该元素
70                 ListDelete_L(&A,pos,&e);
71             /*
72             {flag=ListDelete_L(&A,pos,&e);
73              if(flag)
74              printf("被删除的元素为:%4d
",e);
75              }
76              */
77         }
78     }
79 }
昔日我曾苍老,如今风华正茂(ง •̀_•́)ง
原文地址:https://www.cnblogs.com/lgqrlchinese/p/10104461.html