第2章 线性表 线性结构 是一个数据元素的有序集合。.

Slides:



Advertisements
Similar presentations
第10章 结构体与链表 本章要点: 结构体类型与结构体变量的定义 结构体变量的引用与初始化 结构体数组 链表处理 共用体类型和枚举类型
Advertisements

教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
数据结构概论 第2章 线性表 董黎刚 浙江工商大学信电学院
第三章 鏈結串列 Linked List.
数据结构——树和二叉树 1/96.
数据结构算法 模拟练习及解答二 绍兴文理学院 计算机系计算机应用教研室.
第8章 查找 在英汉字典中查找某个英文单词的中文解释;在新华字典中查找某个汉字的读音、含义;在对数表、平方根表中查找某个数的对数、平方根;邮递员送信件要按收件人的地址确定位置等等。可以说查找是为了得到某个信息而常常进行的工作。 计算机、计算机网络使信息查询更快捷、方便、准确。要从计算机、计算机网络中查找特定的信息,就需要在计算机中存储包含该特定信息的表。如要从计算机中查找英文单词的中文解释,就需要存储类似英汉字典这样的信息表,以及对该表进行的查找操作。本章将讨论的问题即是“信息的存储和查找”。
数据结构 第6章 树和二叉树 什么是树和二叉树?? 二叉树的遍历 数据结构.
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
第二章 线性表.
第2章 线性表 2.1 线性表的概念及运算 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 一元多项式的表示及相加.
C语言基础——指针的高级应用 Week 05.
数据结构与算法 数据结构与算法实验
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
第3章 栈和队列 3.1 栈 3.2 队列 3.3 应用.
單向鏈結串列 Singly Linked Lists.
第4章 串 串的基本概念和C语言的串函数 串的存储结构 动态数组实现的顺序串 串的模式匹配算法——BF算法 主要知识点.
第6章 佇列(Queues) 6-1 佇列的基礎 6-2 佇列的表示法 6-3 環狀佇列 6-4 雙佇列.
第7章 结构体、联合体和枚举类型 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
資料結構 第5章 佇列.
親愛的老師您好 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 博碩文化:
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
结构体和共用体 2 梁春燕 华电信息管理教研室.
第五章 数组和 广义表 数组 稀疏矩阵 广义表.
第五章 数组和广义表.
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
第2章 线性表(三) 1/.
第12章 樹狀搜尋結構 (Search Trees)
Ch.3 栈和队列 黄刘生 中国科学技术大学计算机系 国家高性能计算中心(合肥)
第2章 线性表 2.1 线性表的基本概念 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 线性表的应用 2.5 有序表 本章小结.
第3章 栈和队列(二) 1/.
第2章 线性表 线性表抽象数据类型 顺序表 主要知识点 单链表 循环单链表 循环双向链表 静态链表 设计举例.
第十章 C高级程序应用—链表* 10.1链表的基本概念 10.2单向链表 10.3双向链表 10.4应用举例.
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
第二章 C++对C 在非面向对象方面的改进 更简洁,更安全.
第3章 堆栈和队列 堆栈 堆栈应用 队列 队列应用 优先级队列 主要知识点.
第八章 查找表 8.1静态查找表 8.2动态查找表 8.3哈希表及其查找.
本章重点难点 重点:顺序查找、二分查找、二叉排序树查找以及散列表查找的基本思想和算法实现。
第 3 讲 线性表(一).
第三章 栈和队列 3.1 栈 3.2 栈的应用举例 3.3 栈与递归的实现 3.4 队列.
第3章 栈和队列(一).
第三章 栈和队列.
数据结构 Data Structure 中南大学 主讲人:王国军,郑瑾 中南大学信息院计科系
第二章 线性表.
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
内容回顾 线性表的定义和特点 线性表的顺序存储及查找、插入和删除.
第九章 查找表 9.1静态查找表 9.2动态查找表 9.3哈希表及其查找.
第九章 查找 2019/2/16.
第三章 栈和队列.
資料結構 第4章 堆疊.
严蔚敏、吴伟民编著 清华大学出版社 学习网站:
第三章 链表 单链表 (Singly Linked List) 循环链表 (Circular List) 多项式及其相加
王玲 第 2 章 线性表 王玲 2019/2/25.
教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
7.1 广义表的概念 广义表是n(n≥0)个数据元素组成的序列,其中每个数据元素或是单个数据元素(简称原子),或仍然是一个广义表 。
第十章 结构体与链表 西安工程大学.
第6章 数组与广义表 6.1 数组的定义及其基本操作 6.2 数组的顺序存储结构 6.3 矩阵的压缩存储 6.4 广义表的概念
第六章 树和二叉树 学习要点 理解树的定义和基本术语,重点了解二叉树的定义、性质、存储结构; 掌握二叉树遍历的递归算法及它的典型运算;
本教學投影片係屬教科書著作之延伸,亦受著作權法之保護。
第二章 线性表.
第 六 讲 栈和队列(一).
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
第三章 线性表 3.1 线性表的类型定义 3.2 顺序存储的线性表 3.3 链式存储的线性表 3.4 有序表 3.5 顺序表和链表的综合比较.
Chapter 2 Entity-Relationship Model
本节内容 1.二叉排序树的定义 2.二叉排序树的查找操作 3.二叉排序树的插入操作 4.二叉排序树的删除操作 5.二叉排序树的总结
Presentation transcript:

第2章 线性表 线性结构 是一个数据元素的有序集合。

第2章 线性表 线性结构特征: 1、有且仅有一个开始结点。 2、有且仅有一个终端结点。 3、除开始结点和终端结点外的结点都最多只有一个直接前驱和一个直接后继。

第2章 线性表 2.1 线性表的基本概念 2.2 线性表的顺序存储结构及其运算 2.3 线性表的链式存储结构及其运算 2.4 顺序表和链表的比较 2.5 线性表的应用

2.1 线性表的基本概念 2.1.1 线性表的定义 由数据类型相同的n(n≥0)个数据元素组成的有限序列。 记为(a1,a2, …,ai-1,ai,ai+1, …,an) 其中,n为表长,n=0时称为空表;下标i表示数据元素的位序。通常,用L表示一个线性表。

2.1.2 线性表及其基本操作 1.初始化线性表InitList(L) 初始条件 线性表L不存在。 运算结果 构造一个空的线性表。 运算结果 构造一个空的线性表。 (n=0)。

2.1.2 线性表及其基本操作 2.求线性表的长度LenList(L) 初始条件 表L存在。 运算结果 返回线性表中所含数据元素的个数。

3.读取线性表中的第i个数据元素GetfromList(L,i) 运算结果 返回线性表L中第i个元素的值或地址。如果线性表为空,或者i超过了线性表的长度,则报错。

4.按值查找SearchList(L,x)

5.插入操作InsertList(L,i,x) 初始条件 线性表L存在,i表示新元素将要插入的位置,插入位置正确(1≤i≤n+1,n为插入前的表长)。 运算结果 在L的第i个位置上插入一个值为x的新元素,该元素成为新的第i个数据元素。

6.删除操作:DeleteList(L,i) 运算结果 如果L为空表或位序i大于线性表长度,则报错。在L中删除位序为i的数据元素。

7.PriorElement(L,i) 8 .NextElement(L,i) 9. clearList(L) 10. ListEmpty(L) 根据以上基本操作,可以实现一些复杂的操作。

例如: 假设利用线性表LA和LB分别表示两个集合A和B,现要求构成一个新的集合A=AUB。要求对线性表作如下操作:扩大线性表LA,将存在于LB中而不存在线性表LA中的数据元素插入到线性表LA中去。

1、LB中依次取出每个元素。 2、依次在LA中进行查找。 3、若不存在,则插入之。

线性表的顺序存储结构是指用一组地址连续(存储空间紧邻)的存储单元依次存储线性表的数据元素,用这种存储形式存储的线性表称为顺序表。 2.2 线性表的顺序存储结构及其运算 2.2.1 顺序表 线性表的顺序存储结构是指用一组地址连续(存储空间紧邻)的存储单元依次存储线性表的数据元素,用这种存储形式存储的线性表称为顺序表。

首地址 起始地址 基地址 存储地址 内存状态 元素a1 b 元素a2 b+m …….. 元素ai b+(i-1)*m …….. 每个元素所占用 的存储单元个数 元素an b+(maxlen-1)*m Loc(元素i)=b +(i-1)*m 图2.1 线性表的顺序存储示意图

Loc(ai+1)=Loc(ai)+c l≤i≤n Loc(ai)=Loc(a1)+(i-1)c 设每个元素占用c个存储单元,则第i+1个数据元素的地址为: Loc(ai+1)=Loc(ai)+c l≤i≤n Loc(ai)=Loc(a1)+(i-1)c

#define MAXSIZE 100 typedef struct {DataType elem[MAXSIZE]; /*存放顺序表的容量*/ int length; /*顺序表的实际长度*/ } Sqlist;

typedef struct { DataType *elem; /*线性表的基地址*/ int length; /*线性表当前的长度*/ int listsize; /*线性表当前分配的存储容量*/ }SeqList;

2.2.2 顺序表基本运算的实现 1.初始化 Status InitSeqList(SeqList *L) { /*操作结果:构造一个空的顺序线性表*/ L>elem=(DataType*)malloc(LIST_INIT_SIZE*sizeof(DataType)) if(!L->elem) exit(OVERFLOW); /* 存储分配失败*/ L->length=0; /* 空表长度为0*/ L->listsize=LIST_INIT_SIZE; /*初始存储容量*/ return OK;}

2.插入运算 在表的序号为i的元素前面插入e。 原表 (a1,a2,…,ai-1,ai,ai+1,…,an) 新表(a1,a2,…,ai-1,e,ai, ai+1,…,an) i的合法取值范围1≤i≤n+1

Status InsertSeqList(SeqList *L,int i,DataType e) { /*初始条件:顺序线性表L已存在,1≤i≤ListLength(L)+1*/ /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1*/ DataType *q,*p; if(i<1||i>L->length+1) /* i值不合法*/ return ERROR; else if(L->length>=L->listsize) /*当前存储空间已满,增加分配*/ { printf("顺序表已满");return ERROR;} else { q=L->elem+i; /* q为插入位置*/ for(p=L->elem+L->length;p>=q;--p) /* 插入位置及之后的元素右移*/ *(p+1)=*p; *q=e; /*插入e*/ ++L->length; /*表长增1*/ return OK;} }

时间复杂度为O(n) 在i位置插入e,从ai到an都要向下移动一个位置,共需要移动n-i+1个元素,而i的取值范围为1≤i≤n+1。 插入在i位置的概率为Pi=1/(n+1)。 时间复杂度为O(n)

3.删除运算 删除表中第i个元素。 原表 (a1, a2, …, ai-1, ai, ai+1, …, an) 新表 (a1, a2, …, ai-1, ai+1, …, an) i的取值范围1≤i≤n

int DeleteSeqList(SeqList *L,int i) { /* 初始条件:线性表L已存在,1≤i≤ListLength(L)*/ int j; if(i<1||i>L->length) /* i值不合法*/ { printf("不存在第i个元素!\n"); return 0; } else { for(j=i;j<L->length;j++) L->elem[j]=L->elem[j+1]; /* 向上顺序移动元素*/ L->length--; /* 表长减1*/ return 1;} }

删除第i个元素,元素ai+1~an都要向上移动一个位置,共移动了n-i个元素,Pi=1/n,则有 时间复杂度为O(n)

4.按值查找 在线性表中查找与给定值x相等的数据元素。

while(j<=L->length&&L->elem[j]!=x) j++; if(j>L->length) Status SearchSeqList(SeqList *L, DataType x) { int j=l; while(j<=L->length&&L->elem[j]!=x) j++; if(j>L->length) return(-1); else return j; /*返回x所在位置的位序*/ } 时间复杂度为O(n)

顺序表优点: (1)顺序表随机存取表中元素。 (2)顺序表使用的方法简单,容易编程。 (3)无须增加额外的指针域空间。 缺点: (1)插入、删除操作的效率非常低。 (2)需要预先分配足够大的存储空间,其存储空间长度通常要被预设为线性表使用过程中表长的最大值。

2.3 线性表的链式存储结构及其运算 通过指针反映元素之间的关系,不要求逻辑上相邻的元素在物理位置上也相邻,所以该方法可以克服顺序表的上述缺点,但随之而来的却是随机存取性能的消失。

2.3.1 单链表存储结构 链表中结点的结构如下: data next 数据域,存放数据信息 指针域,指向下一个数据单元

单链表的结点结构如下。 typedef struct node { /*单链表结点结构*/ DataType data ;/* DataType 可以是任何相应的数据类型如int,char等*/ struct node *next; } LinkList;

a1 a2 … ... an ^ 头指针和头结点 头指针 头指针 空指针  头结点 线性表为空表时, 头结点的指针域为空

1、建立单链表。 头插入法,每输入一个不为零整数就建立结点,把结点插入到当前链表的表头之前; 尾插入法,把新生成的结点插入到当前链表的表尾结点之后。 考虑:区别是什么?

(1)头插入法建表 LinkList *AddHead1() { /*用头插入法建立带头结点的单链表*/ int x; LinkList *head,*p; head=( LinkList*)malloc(sizeof(LinkList)); head->next=NULL; /*初始化一个空链表,L为头指针*/ scanf(“%d”,&x); /*x是和链表结点的数据域值具有相同类型的变量*/ while(x!=flag) /*flag为结束输入的标志*/ { p=(LinkList *)malloc(sizeof(LinkList));/*生成新的结点*/ p->data=x; /*输入元素值*/ p->next= head ->next; head ->next=p; /*插入到表头*/ scanf(“%d”,&x); /*读入下一个元素的值*/ } return head;

(2)尾插入法建表 LinkList *AddHead( ) {/*尾插入法建立一个不带头结点的单链表,返回表头指针*/ LinkList *head=NULL,*q=head,*p; int x ; scanf(“%d”,&x); while(x!=flag) { p=(LinkList*)malloc(sizeof(LinkList)); p->data=x; if(head==NULL) head=p; /*第一个结点的处理*/ else q->next=p; /*其他结点的处理*/ q=p; /*q指向新的尾结点*/ } if(q!=NULL) q->next=NULL; /*对于非空表,最后结点的指针域放空指针*/ return head;

2、初始化单链表 void InitList(LinkList *head) {/*初始化带头结点的链表头指针*/ head=(LinkList*)malloc(sizeof(LinkList)); head->next=NULL; }

3、单链表中插入元素 在P所指向的结点之后插入新的结点x ① s=( LinkList *)malloc(sizeof (LinkList)); /*申请新结点,用s保存地址*/ ② s->data=x; /*把值x写入s所指的结点的数据域*/ ③ s->next=p->next; /*令s->next指向p所指结点的下一个结点(或NULL)*/ ④ p->next=s; /*令p->next指向s所指结点*/ 时间复杂度为O(1)。 P a b P a b x S

4、单链表中删除元素 p q ai-1 ai-1 ai ai+1 q = p->next; p->next = q->next; e = q->data; free(q); p q ai-1 ai-1 ai ai+1

5、单链表按序号查找 LinkList *GetNode(LinkList *head,int i) {/*在带头结点的单链表中查找第i个结点,找到返回该结点指针,否则返回NULL*/ LinkList *p=head; int j=0; while(p->next&&j<i) { j++; p=p->next; /*p右移一个结点*/ } if(j==i) return p; else return NULL;

6、单链表按值查找 {/*在带头结点的单链表中查找值为x的结点,找到返回结点指针,否则返回NULL*/ LinkList *LocateNode(LinkList *head,int x) {/*在带头结点的单链表中查找值为x的结点,找到返回结点指针,否则返回NULL*/ LinkList *p=head->next; while(p&&p->data!=x) p=p->next; return p; }

7、求单链表长度 int ListLen(LinkList *head) {/*在带头结点的单链表求表的长度*/ int len=0; LinkList *p=head ; while(p->next!=NULL) { len++; p=p->next; } return len; 算法时间复杂度为O(n)。

2.3.2 循环单链表存储结构 a1 a2 … ... an 和单链表的差别在于,判别链表中最后一个结点的条件不再是“后继是否为空”,而是“后继是否为头结点”。 如果将链表头指针放在头结点的指针域就构成空循环单链表

利用尾指针完成链表L和pL相连的操作。 ① p=L–>next; /*保存L的头结点指针*/ ② L->next=pL->next->next; /*头尾连接*/ ③ free(pL->next); /*释放pL所指链表的头结点*/ ④ pL->next=p; /*重新构成循环单链表*/

2.3.3双向链表存储结构 结点中包含有双向指针的链表。 head head

typedef struct node { ListDT data; struct node *prior,*next; }DNode,*DLink;

双向链表的插入操作 ① q=(DNode*)malloc(sizeof(DNode)); ② q->data=d; ③ q->next=ptr->next; ④ if(ptr->next)ptr->next->prior=q; ⑤ q->prior=ptr; ⑥ ptr->next=q;

① q=(DNode*)malloc(sizeof(DNode)); ② q->data=d; ③ q->prior=ptr->prior; ④ ptr->prior->next=q; ⑤ q->next=ptr; ⑥ ptr->prior=q;

双向链表的删除操作 ai-1 ai-1 ai ai+1 p p->next = p->next->next; p->next->prior = p;

2.4 顺序表和链表的比较

1、顺序表 #define MAXSIZE 100 typedef struct {DataType elem[MAXSIZE]; /*存放顺序表的容量*/ int length; /*顺序表的实际长度*/ } Sqlist;

插入运算:在表的序号为i的元素前面插入e。 元素an …….. 元素ai 元素a2 元素a1 for(j=n;j>=i;j--) a[j+1]=a[j];

删除运算:删除表中第i个元素。 for(j=i;j<n;j++) a[j]=a[j+1]; 元素a1 元素a2 元素ai 元素an …….. 元素ai 元素a2 元素a1 for(j=i;j<n;j++) a[j]=a[j+1];

顺序表优点: (1)可以按序号随机访问表中元素。 (2)比较简单,容易编程。 (3)无须为表示表中元素之间的逻辑关系而增加额外的指针域空间。 缺点: (1)做插入或删除元素的操作时,可能会发生大量的数据移动。 (2)需要预先分配足够大的存储空间。

2.链表 单链表存储结构 data next 数据域,存放数据信息 指针域,指向下一个数据单元

单链表的结点结构如下: typedef struct node { /*单链表结点结构*/ DataType data ;/* DataType 可以是任何相应的数据类型如int,char等*/ struct node *next; } LinkList;

插入运算 s->next=p->next; p->next=s; 时间复杂度为O(1) P a b P a b x S

删除运算 q p ai-1 ai-1 ai ai+1 q = p->next; p->next = q->next; e = q->data; free(q); q p ai-1 ai-1 ai ai+1

链表优点: (1)做插入或删除结点的操作,不会发生数据移动,操作效率比较高。 (2)存储空间占用量是动态的,无须事先分配备用空间。 缺点: (1)不具备随机访问表中元素的特性。 (2)要频繁使用指针,编程难度较大。 (3)需要为表示表中元素之间的逻辑关系而增加额外的指针域空间。

Pn(x)=P0+P1x+P2x2+…+Pnxn 2.5 线性表的应用 【例1】一元多项式写成 Pn(x)=P0+P1x+P2x2+…+Pnxn 线性表表示 P=(P0,P1,P2,…,Pn) 例如: A(x)=1+2x100 +3x1000+4x10000 A=((1,0),(2,100),(3,1000),(4,10000))

单链表表示:

typedef struct pnode {/*多项式结点结构*/ float coef;/*表示多项式的系数*/ int exp; /*表示多项式的指数*/ stuct pnode *next; }Poly;

分三种情况: (1)p->exp<q->exp,*p应为多项式的一项; (2)p->exp==q->exp,则将两个结点中的系数相加,若相加为零,则释放指针p和q所指结点,否则修改*p结点的coef系数域,并释放指针q所指结点; (3)p->exp>q->exp,*q应为多项式的一项,把*q插入到*p之前。

其算法如下: Poly PolyAdd(Poly *pa,Poly *pb) {/*求两多项式之和,多项式用带头结点的单链表表示,pa,pb为头指针*/ Poly *p,*q,*r,*s; int x; p=pa->next; r=pa; /*r为p的前驱指针*/ q=pb->next; free(pb); while(p!=NULL&&q!=NULL) if(p->exp<q->exp) {/*指针顺链向后移动*/ r=p;p=p->next;} else if(p->exp==q->exp) { x=p->coef+q->coef; if(x==0) {r->next=p->next; free(p);/*释放P所指结点*/ } else{ p->coef=x; r=p; } p=r->next; s=q->next;/*s为辅助指针,指向q的后继结点*/ free(q); /*释放q所指结点*/ q=s; } else{/*q所指结点插入到r,p所指结点之间*/ s=q->next;r->next=q; q->next=p; r=q; q=s; } if(q!=NULL) r->next=q;/*将pb表的剩余结点插人到pa表尾*/ return(pa); /*返回新多项式表头指针,与pa一致*/

【例2】为某个单位建立一个员工通讯录管理系统,可以方便查询每一个员工的办公室电话、手机号。 (1)存储结构类型定义 /*员工通讯信息的结构类型定义*/ typedef struct { char num[5]; /*员工编号*/ char name[8]; /*员工姓名*/ char phone[9]; /*办公室电话号码*/ char call[12]; /*手机号码*/ }DataType;

/*通讯录单链表的结点类型*/ typedef struct node { DataType data; /*结点的数据域*/ struct node *next; /*结点的指针域*/ }ListNode,*LinkList;

①建立通讯录链表 LinkList CreatList(void) /*建立一个通讯录链表*/ { LinkList head,s,p,q; char ch; head=(ListNode *)malloc(sizeof(ListNode)); /*创建头结点*/ head->next=NULL; p=head; do{ s=(ListNode *)malloc(sizeof(ListNode)); printf("请输入姓名:"); scanf("%s",s->data.name); printf("请输入编号:"); scanf("%s",s->data.num); printf("请输入电话号码:"); scanf("%s",s->data.phone); printf("请输入手机号码:"); scanf("%s",s->data.call); s->next=p->next; p->next=s; printf("继续输入下一记录吗(y/n)?"); scanf("\n%c",&ch); } while(ch=='y'|| ch=='Y'); return head; /*返回头结点指针*/}

②查询功能:可以按照编号或姓名在链表中顺序查找出对应的记录。 ListNode *SearchList(LinkList head) /*查询函数*/ { ListNode *p; int x; /*按照编号或姓名在链表中查找由x的值决定*/ char num[5]; /*员工编号*/ char name[8]; /*员工姓名*/ printf("1. 按编号查询 2.按姓名查询\n"); printf("请选择:"); scanf("%d",&x); if(x==1) { printf("请输入待查人的编号:"); scanf("%s",num); for(p=head;p!=NULL&&strcmp(p>data.num,num)!=0;p=p->next); } else if(x==2) { printf("请输入待查人的姓名:"); scanf("%s",name); for(p=head;p!=NULL&&strcmp(p->data.name,name)!=0;p=p->next); } return p;}

③插入新的记录:将新记录结点插入到头结点之后,成为链表中的第一个记录结点。也可将新记录插入在记录链表的尾部,成为最后一条记录。 void InsertList(LinkList head,ListNode *p) { p->next=head->next; head->next=p; }

④删除记录:可以按照编号或姓名在链表中顺序查找出对应的记录,然后将其删除。本函数调用查询函数。 void DelNode(LinkList head) { LinkList p,q; char ch; p=SearchList(head); if(!p) { printf("没有找到此人的记录\n"); return;} printf("确定要删除吗?(y/n)"); scanf("\n%c",&ch); if(ch=='n') return; for(q=head;q!=NULL&&q->next!=p;q=q->next); q->next=p->next; free(p); printf("删除成功\n");}

⑤查看全部记录:从第一个结点到最后一个结点依次输出所有记录。 void PrintList(LinkList head) { LinkList p; p=head->next; printf(“编号 姓名 电话号码 手机号码\n”); while(p!=NULL) { printf(" %s%s %s %s\n", p->data.num,p->data.name,p->data.phone,p->data.call); p=p->next; }

结 束!