第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示.

Slides:



Advertisements
Similar presentations
数据结构的引入. 通讯录管理 社团机构管理 校园导航管理 通讯录管理 社团机构管理 校园导航管理.
Advertisements

数据结构概论 第2章 线性表 董黎刚 浙江工商大学信电学院
第二章 线性表 £2.4 线性表的应用 £2.1 线性表的类型定义 £2.2 线性表的顺序存储结构 £2.3 线性表的链式存储结构
第二章 线性表 2.1 线性表的逻辑结构 一. 线性表定义如下:
第二章 线性表 ⒈教学内容:2.1 线性表逻辑结构; 2.2 线性表的顺序存储及运算实现; 2.3 线性表的链式存储和实现。
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
第二章 线性表.
第2章 线性表 2.1 线性表的概念及运算 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 一元多项式的表示及相加.
第2章 线性表 线性结构 是一个数据元素的有序集合。.
其他类型的链表主要内容 静态链表 循环链表 双向链表.
主要内容: 1.第一部分 概述 2.第二部分 线性表、栈、队列
计算机软件技术基础 数据结构与算法(2).
第三章 栈和队列 Stack and Queue
第二章 线性表 线性表 顺序表 链表 顺序表与链表的比较.
数据结构 第2章 线性表 吴忠华.
数 据 结 构 Ch.2 线性表 计 算 机 学 院 肖明军
第三章 线性表 3.1 线性表的类型定义 3.2 顺序存储的线性表 3.3 链式存储的线性表 3.4 有序表 3.5 顺序表和链表的综合比较.
线性表 顺序表 单链表 循环链表 双向链表 多项式
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
第2章 线性表(三) 1/.
数据结构 第二章 线性表.
制作:崔广才
数据结构 Data Structure 中南大学 主讲人:王国军,郑瑾 中南大学信息院计科系
教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
第2章 线性表 2.1 线性表的基本概念 2.2 线性表的顺序存储 2.3 线性表的链式存储 2.4 线性表的应用 2.5 有序表 本章小结.
本 章 说 明 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式存储结构 2.4 循环链表和双向链
西安交通大学计教中心 ctec.xjtu.edu.cn
第2章 线性表 线性表抽象数据类型 顺序表 主要知识点 单链表 循环单链表 循环双向链表 静态链表 设计举例.
第 1 章 数据结构 1.1 基本数据结构与算法 1.2 线性表 1.3 栈和队列 1.4 树和二叉树 1.5 查找 1.6 内部排序 65
第2章 线性表 2.1 线性表 2.2 顺序表 2.3 单链表 2.4 循环单链表 2.5 双向链表 2.6 仿真链表
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
第2章 线性表 丽水学院工学院.
线性表是一种最简单的线性结构 线性结构的基本特征为: 线性结构 是 一个数据元素的有序(次序)集 1.集合中必存在唯一的一个“第一元素”;
第 3 讲 线性表(一).
第三章 栈和队列.
第二章 线性表.
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
内容回顾 线性表的定义和特点 线性表的顺序存储及查找、插入和删除.
第二章 线性表 2.1 线性表的类型定义 2.2线性表的顺序存储 2.3线性表的链式存储 2.4一元多项式的表示和相加.
(知识点三) 2.3 线性表的链式表示和实现 本节将介绍线性表的另一存储结构—— 链式存储及其对应的操作。
线性表练习.
cn/~dongeliu/dsa.html 刘 东 信息学院6系 中国科学技术大学
第四讲 线性表(三) 1/.
第三章 栈和队列.
严蔚敏、吴伟民编著 清华大学出版社 学习网站:
顺序表的插入.
王玲 第 2 章 线性表 王玲 2019/2/25.
第2章 线性表 本章主要介绍下列内容 线性表的定义和基本操作 线性表的顺序存储结构 线性表的链式存储结构 线性表的应用举例.
第二章 线性表.
3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用
严蔚敏、吴伟民编著 清华大学出版社 学习网站:中国网页设计
顺序表的删除.
单链表的基本概念.
顺序查找.
线性结构 线性结构的特点: 线性结构的种类 在数据元素的非空有限集中, (1)存在唯一的一个被称做“第一个”的数据元素;
第 四 讲 线性表(二).
第二章 线性表.
第三章 数据组织与处理.
3.16 枚举算法及其程序实现 ——数组的作用.
第 六 讲 栈和队列(一).
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
实验目的:掌握数据的顺序存储结构及它们在计算机中的操作。 实验内容:
第七讲 栈和队列(二) 1/.
第三章 线性表 3.1 线性表的类型定义 3.2 顺序存储的线性表 3.3 链式存储的线性表 3.4 有序表 3.5 顺序表和链表的综合比较.
算法3.3 void InitList_sq(SqList &L,int msize=LIST_INIT_SIZE)
插入排序的正确性证明 以及各种改进方法.
第二章 线性表 线性表是一种最简单的线性结构 线性结构是一个数据元素的有序(次序)集.
第二部分 数据结构—— 用面向对象方法与C++描述.
§4.5 最大公因式的矩阵求法( Ⅱ ).
第二章 线性表 东南大学计算机学院 方效林 本课件借鉴了清华大学殷人昆老师 和哈尔滨工业大学张岩老师的课件.
Presentation transcript:

第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

本章重点难点 重点: (1) 线性表ADT顺序存储实现中的基本操作及相关算法;(2)ADT链式存储实现中基本操作及相关算法;(3)双向链表的基本操作及相关算法;(4)循环链表的特点、基本操作及相关算法。 难点: 线性表ATD的设计和实现,线性表ADT链式存储实现,包括双向链表、循环链表的基本操作和有关算法。

第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

2.1 线性表的类型定义 线性表的定义 线性表是n 个类型相同数据元素的有限序列, 通常记作(a1, a2, a3, …, an )。 线性结构的基本特征为: (1) 集合中必存在唯一的一个“第一元素”; (2) 集合中必存在唯一的一个“最后元素”; (3)除最后元素在外,均有唯一的后继; (4)除第一元素之外,均有唯一的前驱。

见下页 2.1 线性表的类型定义 线性结构的基本特征为: ADT List { 2.1 线性表的类型定义 线性结构的基本特征为: ADT List { 数据对象: D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 } {称 n 为线性表的表长; 称 n=0 时的线性表为空表。} 数据关系: R1={ <ai-1 ,ai >|ai-1 ,ai∈D, i=2,...,n } 基本操作: 见下页 }ADT List

2.1 线性表的类型定义 基本操作 InitList( &L ) //构造一个空的线性表L。 DestroyList( &L ) //销毁L ListEmpty( L ) //判断L是否空 ListLength( L ) //求L的长度 PriorElem( L, cur_e, &pre_e ) //求前驱的值 NextElem( L, cur_e, &next_e ) //求后继的值

2.1 线性表的类型定义 基本操作 GetElem( L, i, &e ) //取i位置的值 LocateElem( L, e, compare( ) ) //在线性表中查找e ListTraverse(L, visit( )) //遍历线性表 ClearList( &L ) //清空线性表 ListInsert( &L, i, e ) //在i位置插入e ListDelete(&L, i, &e) //删除i位置的元素

2.1 线性表的类型定义 基本操作的应用 用定义过的基本操作实现例2-1,例2-2 例 2-1 假设:有两个集合 A 和 B 分别用两个线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合A=A∪B。

2.1 线性表的类型定义 例2-1操作步骤: (1) 从线性表LB中依次察看每个数据元素; GetElem(LB, i,&e) (2) 依值在线性表LA中进行查访; LocateElem(LA, e, equal( )) (3) 若不存在,则插入之。 ListInsert(LA, n+1, e)

2.1 线性表的类型定义 例2-1算法 void union(List &La, List Lb) { La_len = ListLength(La); // 求线性表的长度 Lb_len = ListLength(Lb); for (i = 1; i <= Lb_len; i++) { ……………………………. } }

2.1 线性表的类型定义 例2-1算法 GetElem(Lb, i, e); // 取Lb中第i个数据元素赋给e if (!LocateElem(La, e, equal( )) ) ListInsert(La, ++La_len, e); // La中不存在和 e 相同的数据元素,则插入之 例2-1算法时间复杂性 O(ListLength(La)*ListLength(Lb))

2.1 线性表的类型定义 基本操作的应用 用定义过的基本操作实现例2-2 例 2-2 将两个“数据元素按值递增有序排列”的线性表La和Lb归并到线性表Lc,且Lc具有同样的性质。 设 La=(a1,…ai,….an) Lb=(b1,…bj,….bm) Lc=(c1,…ck,…cm+n)

见下页 2.1 线性表的类型定义 例2-2算法 void MergeList(List La, List Lb, List &Lc) { 2.1 线性表的类型定义 例2-2算法 void MergeList(List La, List Lb, List &Lc) { } // merge_list InitList(Lc); // 构造空的线性表 Lc i = j = 1; k = 0; La_len = ListLength(La); Lb_len = ListLength(Lb); while ((i <= La_len) && (j <= Lb_len)) { // La 和 Lb 均不空 } while (i<=La_len) // 若 La 不空 while (j<=Lb_len) // 若 Lb 不空 见下页

2.1 线性表的类型定义 例2-2算法 GetElem(La, i, ai); GetElem(Lb, j, bj); if (ai <= bj) { // 将 ai 插入到 Lc 中 ListInsert(Lc, ++k, ai); ++i; } else { // 将 bj 插入到 Lc 中 ListInsert(Lc, ++k, bj); ++j;

2.1 线性表的类型定义 例2-2算法 while (i <= La_len) { // 当La不空时 GetElem(La, i++, ai); ListInsert(Lc, ++k, ai); } // 插入 La 表中剩余元素 while (j <= Lb_len) { // 当Lb不空时 GetElem(Lb, j++, bj); ListInsert(Lc, ++k, bj); } // 插入 Lb 表中剩余元素

第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

存储线性表,就是要保存至少两类信息: (1) 线性表中的数据元素; (2) 线性表中数据元素的顺序关系; 2.2 线性表的顺序表示和实现 存储线性表,就是要保存至少两类信息: (1) 线性表中的数据元素; (2) 线性表中数据元素的顺序关系; 如何在计算机中存储线性表? 如何在计算机中实现线性表的 基本操作?

2.2 线性表的顺序表示和实现 线性表的顺序表示的定义 以数据元素x 的存储位置和数据元素 y 的存储位置之间的某种关系表示逻辑关系<x,y>。 线性表的顺序表示最简单的一种顺序映象方法是:令x的存储位置和y 的存储位置相邻。

2.2 线性表的顺序表示和实现 线性表的顺序表示图示 用一组地址连续的存储单元依次存放线性表中的数据元素 a1 a2 … ai-1 ai … an 线性表的起始地址 称作线性表的基地址

2.2 线性表的顺序表示和实现 数据元素地址之间的关系 以“存储位置相邻”表示有序对<ai-1,ai>时, ai-1和ai的地址关系如下: LOC(ai) = LOC(ai-1) + C C为一个数据元素所占存储量 所有数据元素的存储位置均取决于第一个数据元素的存储位置。 LOC(ai) = LOC(a1) + (i-1)×C ↑基地址

2.2 线性表的顺序表示和实现 顺序表示的实现 #define LIST_INIT_SIZE 80 // 线性表存储空间的初始分配量 #define LISTINCREMENT 10 // 线性表存储空间的分配增量 typedef struct { } SqList; // 俗称 顺序表 ElemType *elem; // 存储空间基址 int length; // 当前长度 int listsize; // 当前分配的存储容量 // (以sizeof(ElemType)为单位)

2.2 线性表的顺序表示和实现 基本操作的实现 Status InitList_Sq( SqList &L ) { // 构造一个空的线性表 } // InitList_Sq L.elem = (ElemType*) malloc (LIST_ INIT_SIZEsizeof (ElemType)); if (!L.elem) exit(OVERFLOW); L.length = 0; L.listsize = LIST_INIT_SIZE; return OK;

2.2 线性表的顺序表示和实现 基本操作的实现 线性表操作 ListInsert(&L, i, e)的实现: 首先分析: 插入元素时, 线性表的逻辑结构发生什么变化?

2.2 线性表的顺序表示和实现 插入操作过程示意图 a1 a2 … ai-1 ai ai+1 an a1 a2 … ai-1 ai ai+1 2.2 线性表的顺序表示和实现 插入操作过程示意图 a1 a2 … ai-1 ai ai+1 an a1 a2 … ai-1 ai ai+1 an a1 a2 … ai-1 e ai+1 an

2.2 线性表的顺序表示和实现 插入操作算法 Status ListInsert_Sq(SqList &L, int i, ElemType e) { // 在顺序表L的第 i 个元素之前插入新的元素e } // ListInsert_Sq …… q = &(L.elem[i-1]); // q 指示插入位置 for (p = &(L.elem[L.length-1]); p >= q; --p) *(p+1) = *p; // 插入位置及之后的元素右移 *q = e; // 插入e ++L.length; // 表长增1 return OK;

if (i < 1 || i > L.length+1) return ERROR; // 插入位置不合法 2.2 线性表的顺序表示和实现 插入操作算法 if (i < 1 || i > L.length+1) return ERROR; // 插入位置不合法 if (L.length >= L.listsize) { // 当前存储空间已满,增加分配 newbase = (ElemType *)realloc(L.elem, (L.listsize+LISTINCREMENT)*sizeof (ElemType)); if (!newbase) exit(OVERFLOW); L.elem = newbase; // 新基址 L.listsize += LISTINCREMENT; }

O(n) 2.2 线性表的顺序表示和实现 插入算法时间复杂性分析 2.2 线性表的顺序表示和实现 插入算法时间复杂性分析 设在第i个元素之前插入的概率为pi,则在长度为n的线性表中插入一个元素时所需平均移动元素次数为: 若假定在任何一个位置上插入元素的概率相同,则平均移动次数为: O(n)

2.2 线性表的顺序表示和实现 基本操作的实现 线性表删除操作ListDelete(&L, i, &e)的实现: 首先分析: 删除元素时, 线性表的逻辑结构发生什么变化?

2.2 线性表的顺序表示和实现 删除操作过程示意图 a1 a2 … ai-1 ai ai+1 an a1 a2 … ai-1 ai+1 an

2.2 线性表的顺序表示和实现 删除操作过程示意图 Status ListDelete_Sq (SqList &L, int i, ElemType &e) { } // ListDelete_Sq if ((i < 1) || (i > L.length)) return ERROR; p = &(L.elem[i-1]); // p 为被删除元素的位置 e = *p; // 被删除元素的值赋给 e q = L.elem+L.length-1; // 表尾元素的位置 for (++p; p <= q; ++p) *(p-1) = *p; --L.length; // 表长减1 return OK;

2.2 线性表的顺序表示和实现 删除操作时间复杂性分析 设删除第i个元素的概率为pi,则在长度为n的线性表中删除一个元素时所需平均移动次数为: 若假定在任何一个位置上删除元素的概率相同,则平均移动次数为: O(n)

2.2 线性表的顺序表示和实现 顺序表的优缺点 (1) 优点    a.节省存储空间; b.对线性表中第i个结点的操作易于实现; c.容易查找一个结点的前驱和后继。 (2)缺点 a.插入和删除操作比较困难; b.建立空表时,较难确定所需的存储空间。

第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

2.3 线性表的链式表示和实现 2.3.1 单链表 2.3.2 静态链表 2.3.3 循环链表 2.3.4 双向链表

2.3.1 单链表 链表的定义 一个线性表由若干个结点组成,每个结点至少含有两个域:数据域(信息域)和指针域(链域),由这样的结点形成存储的线性表称作链表。 单链表结构示意图 … a1 a2 an ^

… 2.3.1 单链表 单链表结构示意图 结构特点 逻辑次序和物理次序 相同; 不一定 2.3.1 单链表 单链表结构示意图 … a1 a2 an ^ 结构特点 逻辑次序和物理次序 相同; 元素之间的逻辑关系用 表示;需要额外空间存储元素之间的关系; 是不是随机存储结构? 不一定 指针 不是

… 2.3.1 单链表 头指针的概念 在链式存储结构中以第一个结点的存储地址作为线性表的基地址,通常称它为头指针。 2.3.1 单链表 头指针的概念 在链式存储结构中以第一个结点的存储地址作为线性表的基地址,通常称它为头指针。 … a1 a2 an ^ 线性表的最后一个数据元素没有后继,因此最后一个结点中的"指针"是一个特殊的值 "NULL",通常称它为"空指针"。

… 2.3.1 单链表 头结点的概念 在单链表上设置一个结点,它本身不存放数据,它的指针域指向第一个元素的地址。 头结点的作用 2.3.1 单链表 头结点的概念 在单链表上设置一个结点,它本身不存放数据,它的指针域指向第一个元素的地址。 … a1 a2 an ^ 头结点的作用 使对第一个元素的操作与对其它元素的操作保持一致。

2.3.1 单链表 单链表的C语言实现 Typedef struct LNode { ElemType data; // 数据域 struct Lnode *next; // 指针域 } LNode, *LinkList; LinkList L; // L 为单链表的头指针

2.3.1 单链表 单链表操作的实现 GetElem_L(LinkList L, int i, ElemType &e) //查找第i个结点,将第i个结点的值存入e 查找过程 (1)从第一个结点p开始,j=1开始记数; (2)当p->next不为空时,转向下一个继续记数; (3)直到j=i或p->next为空。

2.3.1 单链表 GetElem_L算法 Status GetElem_L(LinkList L, int i, ElemType &e) { } p = L->next; j = 1; // p指向第一个结点,j为计数器 while (p && j<i) { p = p->next; ++j; } if ( !p) return ERROR; // 第 i 个元素不存在 e = p->data; // 取得第 i 个元素 return OK;

2.3.1 单链表 单链表操作的实现 Status ListInsert_L(LinkList L, int i, ElemType e) // L 为带头结点的单链表的头指针,本算法 // 在链表中第i 个结点之前插入新的元素 e 插入过程 (1)查找第i-1个结点p; (2)生成结点s,存入e; (3)s->netx=p->next, p->next=s;

2.3.1 单链表 ListInsert_L算法 Status ListInsert_L(LinkList L, int i, ElemType e) { // L 为带头结点的单链表的头指针,本算法 // 在链表中第i 个结点之前插入新的元素 e } // LinstInsert_L p = L; j = 0; while (p && j < i-1) { p = p->next; ++j; } // 寻找第 i-1 个结点 if (!p ) return ERROR; // i 大于表长或者小于1 ……

2.3.1 单链表 ListInsert_L算法 s = (LinkList) malloc ( sizeof (LNode)); // 生成新结点 s->data = e; s->next = p->next; p->next = s; // 插入 return OK; ListInsert_L算法的时间杂性 O(ListLength(L))

2.3.1 单链表 单链表操作的实现 ListDelete_L(LinkList L, int i, ElemType &e) // L 为带头结点的单链表的头指针,本算法 // 删除链表中第i 个结点,值储入 e 删除过程 (1) 查找第i-1个结点p; (2) q=p->netx,p->next=q->next (3) free(q)

2.3.1 单链表 ListDelete_L算法 Status ListDelete_L(LinkList L, int i, ElemType &e) { } // ListDelete_L p = L; j = 0; while (p->next && j < i-1) { p = p->next; ++j; } if (!(p->next) ) return ERROR; // 删除位置不合理 q = p->next; p->next = q->next; e = q->data; free(q); return OK;

2.3.1 单链表 单链表应用举例 例 2-3 将两个“数据元素按值递增有序排列”的线性表La和Lb归并到线性表Lc,且Lc具有同样的性质。 设 La=(a1,…ai,….an) Lb=(b1,…bj,….bm) Lc=(c1,…ck,…cm+n)

2.3.1 单链表 例2-3算法 Status MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc) {LinkList pa=La->next,pb=Lb->next,pc=Lc=La; while(pa&&pb) { if(pa->data<=pb->data) {pc->next=pa;pc=pa;pa=pa->next;} else {pc->next=pb;pc=pb;pb=pb->next;} } pc->next=pa?pa:pb; free(Lb); } // MergeList_L

2.3.1 单链表 链表的优缺点 (1) 优点    a. 插入和删除时间复杂性低; b.不需预先分配空间。 (2)缺点 a.指针占用存储空间,增加了内存负担。

2.3 线性表的链式表示和实现 2.3.1 单链表 2.3.2 静态链表 2.3.3 循环链表 2.3.4 双向链表

2.3.2 静态链表 静态链表的引入 链表具有不需事先分配存储空间,插入和删除操作时间复杂性低等优点,但实现链表必须能够对内存地址进行操作,但直接对内存地址进行操作是很多高级语言不具备的功能,为了在不具备地址操作的高级语言上实现链表的功能,引入了静态链表。 静态链表的概念 定义一个较大的结构数组作为备用结点空间(即存储池),当申请结点时,从存储池中取出一个结点,当释放结点时,将结点归还存储池内。

space[1],space[3],space[5], space[6]. 2.3.2 静态链表 存储池 space 静态链表示意图 1 2 3 4 5 6 7 8 9 10 9 zhao 3 qian 4 sun 5 li 7 zhou 6 wu zheng 8 wang 10 静态链表的第一个结点位置是一个下标: 左图中有两个静态链表 第一个以1开头。 space[1],space[3],space[5], space[6]. 第二个以2开头 space[2],space[4],space[7], space[8]. data域 cur域

2.3.2 静态链表 静态链表的C语言实现 //----线性表的静态单链表存储结构----// #define MAXSIZE 1000 //链表的最大长度 typedef struct { ElemType data; int cur; //游标 } component, SLinkList[MAXSIZE]; SLinkList space;

2.3.2 静态链表 静态链表模拟可用空间初始化 //----初始化----// void InitSpace_SL(SLinkList &space) { for (i=0;i<MAXSIZE-1;++i) space[i].cur=i+1; space[MAXSIZE-1].cur=0; }

2.3.2 静态链表 静态链表模拟申请空间的实现 //----申请空间----// int Malloc_SL(SLinkList &space) { i = space[0].cur; if (space[0].cur) space[0].cur = space[i].cur; return i; }

2.3.2 静态链表 静态链表模拟释放空间的实现 //----回收结点----// void Free_SL(SLinkList &space,int K) { space[k].cur=space[0].cur; space[0].cur=k; }

2.3.2 静态链表 静态链表插入算法 Status ListInsert_L(int L, int i, ElemType e) { // L 为静态链表的第一个结点位置,本算法 // 在链表中第i 个结点之前插入新的元素 e } p =L; j = 0; while (p && j < i-1) { p =space[p].cur; ++j; } if (!p) return ERROR; ……

2.3.2 静态链表 静态链表插入算法 s = Malloc_SL(space) // 生成新结点 space[s].data = e; space[s].cur =space[p].cur; space[p].cur = s; // 插入新结点 return OK; 静态链表插入算法时间复杂性 O(ListLength(L))

2.3 线性表的链式表示和实现 2.3.1 单链表 2.3.2 静态链表 2.3.3 循环链表 2.3.4 双向链表

2.3.3 循环链表 循环链表的概念 单链表最后一个结点的指针域没有利用,如果使其指向指向头指针(头结点),则首尾构成一个循环,称作循环链表。 循环链表示意图 … a1 a2 an head

… 2.3.3 循环链表 循环链表的优点 从表中任一结点出发均可找到表中其它结点。 讨论:在循环链表中多采用尾指针?为什么? 2.3.3 循环链表 循环链表的优点 … a1 a2 an head 从表中任一结点出发均可找到表中其它结点。 讨论:在循环链表中多采用尾指针?为什么? 结论:如果采用尾指针,则查找第一个结点和最后一个结点都容易。

2.3.3 循环链表 单链表和循环链表操作比较 设两个链表La=(a1,a2,...,an)和Lb=(b1,b2,...bm),讨论如下问题: (1) La、Lb都是带头结点的单链表,如何实现将Lb接在La之后?时间复杂度是多少? (2) La、Lb都是带头结点头指针的单循环链表,如何实现将Lb接在La之后还形成一个循环链表?时间复杂度是多少? (3) La、Lb都是带头结点尾指针的单循环链表,如何实现将Lb接在La之后还形成一个循环链表?时间复杂度是多少?

2.3.3 循环链表 单链表和循环链表操作比较 结论: (1) La、Lb都是带头结点的单链表,Lb接在La之后,时间复杂度是 O(length(La))。 (2) La、Lb都是带头结点头指针的单循环链表,实现将Lb接在La之后还形成一个循环链表,时间复杂度是多少 O(length(La)+length(Lb))。 (3) La、Lb都是带头结点尾指针的单循环链表,实现将Lb接在La之后还形成一个循环链表,时间复杂度是 O(1)。

一个链表的每一个结点含有两个指针域:一个指针指向其前驱结点,另一个指针指向其后继结点,这样的链表称为双向链表。 2.3.3 双向链表 双向链表的概念 一个链表的每一个结点含有两个指针域:一个指针指向其前驱结点,另一个指针指向其后继结点,这样的链表称为双向链表。 双向链表结构示意图 ^ a1 a2 … ^ head

2.3.3 双向链表 双向链表的C语言实现 //类型定义 typedef struct DuLNode{ ElemType data; struct DuLNode *prior; struct DuLNode *next; } DuLNode,*DuLinkList;

2.3.3 双向链表 双向链表中地址关系 在双向链表中: p->prior指向p的前驱,p->next指向p的后继 以下都是p结点的地址: p->next->prior 和 p->prior->next 双向链表的操作特点: “查询” 和单链表相同。 “插入” 和“删除”时需要同时修改两个方向上的指针。

2.3.3 双向链表 双向链表的插入算法 Status ListInsert_Dul(DuLinkList &L, int i ,ElemType e) { if(!(p=GetElemP_DuL(L,i))) return error; if(!(s=(DuLinkList)malloc(sizeof(DuLNode)))) s->data=e; s->prior=p->prior; s->next=p; p->prior->next=s; p->prior=s; return OK; }

2.3.3 双向链表 双向链表的删除算法 Status ListDelete_Dul(DuLinkList &L,int i ,ElemType &e) { if(!(p=GetElemP_DuL(L,i))) return error; e=p->data; p->prior->next=p->next; p->next->prior=p->prior; free(p); return OK; }

第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

2.4 一元多项式的表示 一元多项式的讨论 讨论一元多项式用什么方式存储比较合适? 结论:一元多项式既可以用顺序表存储,也可以用链表存储,在用顺序表存储时,如果是稀疏多项式则浪费空间严重,用链式存储比较好。

见下页 2.4 一元多项式的表示 一元多项式的抽象数据类型 ADT Polynomial { 数据对象: 2.4 一元多项式的表示 一元多项式的抽象数据类型 ADT Polynomial { 数据对象: 数据关系: } ADT Polynomial D={ ai | ai ∈TermSet, i=1,2,...,m, m≥0 TermSet 中的每个元素包含一个 表示系数的实数和表示指数的整数 } R1={ <ai-1 ,ai >|ai-1 ,ai∈D, i=2,...,n 且ai-1中的指数值<ai中的指数值 } 基本操作: 见下页

2.4 一元多项式的表示 一元多项式的基本操作 CreatPolyn ( &P, m ) //存储多项式 DestroyPolyn ( &P ) //销毁多项式 PrintPolyn ( &P ) //打印输出多项式 PolynLength( P ) //求多项式的项数 AddPolyn ( &Pa, &Pb ) //两个多项式相加 SubtractPolyn ( &Pa, &Pb )//两个多项式相减 ……

2.4 一元多项式的表示 一元多项式类型的C语言实现 typedef struct { // 项的表示 float coef; // 系数 int expn; // 指数 } term, ElemType; typedef LinkList polynomial; // 用带表头结点的有序链表表示多项式

本章小结 熟练掌握: (1)线性表的逻辑结构特性和线性表的(ADT)设计; (2)线性表的顺序存储结构和链式存储结构两种实现方式和基本操作; (3)双向链表的插入和删除等基本操作及相关算法; (4)循环链表的特点及相关操作; (5)理解一元多项式的表示方法及相加算法,提高自己用线性表解决实际问题的应用水平。