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

实验内容:

1.建立单链表A与B

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

3.实现操作A-B

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

 #include <stdio.h>

 #include <stdlib.h>

 typedef int ElemType;

步骤2:定义结构体LNode

 typedef struct LNode

 {

      ElemType data;

      struct LNode *next;

 }LNode, *LinkList;

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

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

步骤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;

 void InitList_L(LinkList *L)

 {

      *L=(LinkList)malloc(sizeof(LNode));

      if (*L==NULL)

          exit(-);

      (*L)->next=NULL;

      //等价于(*(*L)).next=NULL;                                              

 }

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

 int ListInsert_L(LinkList L,int i,ElemType e)

 {
LNode *p,*s;
int j;
p=L;
j=;
while(p&&j<i-)
{
p=p->next;++j;
}
if(!p||j>i-)
return ;
s=(LinkList)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return ;
}

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

 int GetElem_L(LinkList L, int i, ElemType *e)
{
LinkList p;
int j=;
p=L->next;
while(p&&j<i)
{
p=p->next;
++j;
}
if(!p||j>i)
return ;
*e=p->data;
return ;
}

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

 int ListSize_L(LinkList L)
{
LNode *p;
int count=;
p=L;
while(p->next!=NULL)
{
p=p->next;
count++;
}
return count;
}

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

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

 int main()
{
int i,flag,e;
//定义两个头指针
LinkList A,B;
//测试函数GetElemPointer_L()
LNode *p;
/*初始化单链表A,将头指针A的地址(即指向A的指针)传入*/
InitList_L(&A);
/*初始化单链表B,将头指针B的地址(即指向B的指针)传入*/
InitList_L(&B);
/*为单链表A填充数据*/
ListInsert_L(A,,);

ListInsert_L(A,,);
/*为单链表B填充数据*/
ListInsert_L(B,,);

ListInsert_L(B,,);
/*输出单链表A*/
printf("单链表A中的元素为:\n");
for(i=;i<=ListSize_L(A);i++)
{
flag=GetElem_L(A,i,&e);
if(flag)
printf("%4d",e);
}
printf("\n");
/*输出单链表B*/
printf("单链表B中的元素为:\n");
for(i=;i<=ListSize_L(B);i++)
{
flag=GetElem_L(B,i,&e);
if(flag)
printf("%4d",e);
}
printf("\n");
}

步骤4的输出结果

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

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

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

步骤6:测试函数ListDelete_L()

     flag=ListDelete_L(&B,,&e);
if(flag)
printf("被删除的元素为:%4d",e);
printf("\n");
printf("单链表B中的剩余元素为:\n");
for(i=;i<=ListSize_L(B);i++)
{
flag=GetElem_L(B,i,&e);
if(flag)
printf("%4d",e);
}
printf("\n");


步骤6的输出结果

步骤7:实现函数LocateElem_L
()

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

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

该函数声明为:

 int LocateElem_L(LinkList L, ElemType e);

步骤8:测试函数LocateElem_L()

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


步骤8的输出结果

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

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

该函数声明为:

 LNode *GetElemPointer_L(LinkList L,int i);

步骤10:测试函数GetElemPointer_L()

 p=GetElemPointer_L(A,);
printf("单链表A中的第3个元素为:%4d\n",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()的声明如下:

 void DelElem_L(LinkList A,LinkList B);

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

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


步骤12的输出结果

思考题

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

 /*删除指定位置上的元素*/
int ListDelete_L(LinkList *L,int i, ElemType *e) {
LNode *p,*q;
p=*L;
int j=;
while(p->next&&j<i-) {
p=p->next;
++j;
}
if(!(p->next)||j>i-) return ;
q=p->next;
p->next=q->next;
*e=q->data;
free(q);
return ;
} /*返回给定元素在单链表中的位置*/
int LocateElem_L(LinkList L, ElemType e) {
LNode *p;
int i;
if(L->next==NULL)
return ;
p=L->next;
i=;
while(p) { if(p->data==e)
return i;
else {
p=p->next;
i++;
}
if(!p) return ;
}
} /*返回指向单链表中第i个元素的指针*/
/*若找到第i个结点,则返回指向该结点的指针;否则,返回空指针*/
LNode *GetElemPointer_L(LinkList L,int i) {
LNode *p;
int j;
//若单链表为空
if(L->next==NULL)
return NULL;
//若参数非法
if(i<)
return NULL;
p=L;
j=;
while(p->next!=NULL&&j<i) {
p=p->next;
j++;
}
if(j==i)
return p;
else
return NULL;
} void DelElem_L(LinkList A,LinkList B) {
int i,pos,flag;
ElemType e;
LNode *p;
for(i=; i<=ListSize_L(B); i++) {
p=GetElemPointer_L(B,i);//p指向单链表B中存在第i个结点
if(p) { //若单链表B中存在第i个结点
pos=LocateElem_L(A,p->data);//若A中存在相同的结点,则用返回其在A中的位置
if(pos>)//若存在,则在A中删除该元素
ListDelete_L(&A,pos,&e);
/*
{flag=ListDelete_L(&A,pos,&e);
if(flag)
printf("被删除的元素为:%4d\n",e);
}
*/
}
}
}

大学实验3指导:利用单链表实现A-B的更多相关文章

  1. VLAN实验4:利用单臂路由实现VLAN间路由

    单臂路由: 实验环境: 实验拓扑图: 实验编址: 实验步骤:1.创建VLAN并配置Access.Trunk接口. 我们在S2上创建VLAN10和VLAN20,并且吧链接PC1的E0/0/1和链接PC2 ...

  2. 148. Sort List (java 给单链表排序)

    题目:Sort a linked list in O(n log n) time using constant space complexity. 分析:给单链表排序,要求时间复杂度是O(nlogn) ...

  3. Python与数据结构[0] -> 链表/LinkedList[0] -> 单链表与带表头单链表的 Python 实现

    单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利 ...

  4. 利用单臂路由实现VLAN间的路由

    实验4:利用单臂路由实现VLAN间的路由. 实验原理:  实验内容: 本实验模拟公司网络场景,路由器R1是公司的出口网关,员工PC通过接入层交换机(如S2和S3)接入公司网络,接入层交换机又通过汇聚交 ...

  5. SDUT OJ 数据结构实验之链表七:单链表中重复元素的删除

    数据结构实验之链表七:单链表中重复元素的删除 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem ...

  6. SDUT OJ 数据结构实验之链表五:单链表的拆分

    数据结构实验之链表五:单链表的拆分 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...

  7. 数据结构实验2:C++实现单链表类

    太简单了,直接贴题目然后上代码. 题目: 实验2 2.1 实验目的 熟练掌握线性表的链式存储结构. 熟练掌握单链表的有关算法设计. 根据具体问题的需要,设计出合理的表示数据的链式存储结构,并设计相关算 ...

  8. SDUT-2120_数据结构实验之链表五:单链表的拆分

    数据结构实验之链表五:单链表的拆分 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入N个整数顺序建立一个单链表,将该 ...

  9. SDUT-2122_数据结构实验之链表七:单链表中重复元素的删除

    数据结构实验之链表七:单链表中重复元素的删除 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 按照数据输入的相反顺序(逆 ...

随机推荐

  1. nrf2401 - 最廉价的2.4G无线通信方案

    所有的使用Arduino 的朋友大多都会知道大名鼎鼎的XBee 这个土豪级的ZigBee 的通信模块.我们是做产品开发的,对于XBee这个产品可谓是又爱又恨,不得不承认他确实是一个好货,从做工到功能都 ...

  2. struts2的基本使用

    struts2在web中当作前端控制器,接收来自页面的请求,使用过滤器拦截模式对请求进行拦截并交给相应配置的action类处理. 所以在web中使用最重要的是struts2的核心过滤器StrutsPr ...

  3. Wannafly挑战赛28

    总结- A-开始觉得是找规律,最开始模拟当时我觉得如果L达到1e9的范围的话,岂不是要加1e9次,模拟也就没有认真写,现在想来,后面由于加的不再是1,而是我前面的值,这样相当了一个斐波那契的类型,而斐 ...

  4. c++入门之文件读取

    再次强调这个观念:写文件,读文件和读,写控制台本质上没有区别,意识到这一点是十分重要的.下面给出读文件的代码: #include "iostream" # include &quo ...

  5. Division and Union CodeForces - 1101C (排序后处理)

    There are nn segments [li,ri][li,ri] for 1≤i≤n1≤i≤n. You should divide all segments into two non-emp ...

  6. linux下编译upx ucl

    昨天,UPX发布了3.93版本. UPX(the Ultimate Packer for eXecutables)是一个非常全面的可执行文件压缩软件,支持dos/exe.dos/com.dos/sys ...

  7. Arrays.copyOf() 和 System.arrayCopy()分析

    java数组的拷贝四种方法:for.clone.System.arraycopy.Arrays.copyof public class Test1 { public static void main( ...

  8. hdu2089_不要62

    不要62 题目大意:给你一个区间,算出该区间里不含62或4的数的个数 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 /* // 暴力就可以过了 ...

  9. 将form数据转换成json对象自定义插件实现思路

  10. C# Note21: 扩展方法(Extension Method)及其应用

    前言 今天在开会时提到的一个概念,入职3个多月多注重在项目中使用C#的编程知识,一直没有很认真地过一遍C#的全部语法,当我们新人被问及是否了解Extension Method时,一时之间竟不能很通俗准 ...