第二章 线性表 线性表 顺序表 链表 顺序表与链表的比较.

Slides:



Advertisements
Similar presentations
第三章 鏈結串列 Linked List.
Advertisements

第二章 线性表 £2.4 线性表的应用 £2.1 线性表的类型定义 £2.2 线性表的顺序存储结构 £2.3 线性表的链式存储结构
第二章 线性表 2.1 线性表的逻辑结构 一. 线性表定义如下:
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
第二章 线性表 ⒈教学内容:2.1 线性表逻辑结构; 2.2 线性表的顺序存储及运算实现; 2.3 线性表的链式存储和实现。
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
第二章 线性表.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
單向鏈結串列 Singly Linked Lists.
第2章 线性表 线性结构 是一个数据元素的有序集合。.
其他类型的链表主要内容 静态链表 循环链表 双向链表.
计算机软件技术基础 数据结构与算法(2).
第三章 栈和队列 Stack and Queue
第7章 结构体、联合体和枚举类型 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
佇列 (Queue).
数 据 结 构 Ch.2 线性表 计 算 机 学 院 肖明军
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
线性表 顺序表 单链表 循环链表 双向链表 多项式
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
第2章 线性表(三) 1/.
制作:崔广才
数据结构 Data Structure 中南大学 主讲人:王国军,郑瑾 中南大学信息院计科系
教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
本 章 说 明 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
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
第2章 线性表 丽水学院工学院.
第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示.
线性表是一种最简单的线性结构 线性结构的基本特征为: 线性结构 是 一个数据元素的有序(次序)集 1.集合中必存在唯一的一个“第一元素”;
第二章 线性表.
第 六 章 鏈結串列(Link List) 課程名稱:資料結構 授課老師:________ 2019/1/2.
五、链 表 1、单链表 2、双向链表 3、链表应用.
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
内容回顾 线性表的定义和特点 线性表的顺序存储及查找、插入和删除.
第二章 线性表 2.1 线性表的类型定义 2.2线性表的顺序存储 2.3线性表的链式存储 2.4一元多项式的表示和相加.
(知识点三) 2.3 线性表的链式表示和实现 本节将介绍线性表的另一存储结构—— 链式存储及其对应的操作。
线性表练习.
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
cn/~dongeliu/dsa.html 刘 东 信息学院6系 中国科学技术大学
第三章 链表 单链表 (Singly Linked List) 循环链表 (Circular List) 多项式及其相加
顺序表的插入.
王玲 第 2 章 线性表 王玲 2019/2/25.
第2章 线性表 本章主要介绍下列内容 线性表的定义和基本操作 线性表的顺序存储结构 线性表的链式存储结构 线性表的应用举例.
3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
严蔚敏、吴伟民编著 清华大学出版社 学习网站:中国网页设计
第五章 递归与广义表 递归的概念 递归过程与递归工作栈 递归与回溯 广义表.
程式結構&語法.
顺序表的删除.
单链表的基本概念.
顺序查找.
线性结构 线性结构的特点: 线性结构的种类 在数据元素的非空有限集中, (1)存在唯一的一个被称做“第一个”的数据元素;
第 四 讲 线性表(二).
本教學投影片係屬教科書著作之延伸,亦受著作權法之保護。
第二章 线性表.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第三章 数据组织与处理.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
实验目的:掌握数据的顺序存储结构及它们在计算机中的操作。 实验内容:
第三章 线性表 3.1 线性表的类型定义 3.2 顺序存储的线性表 3.3 链式存储的线性表 3.4 有序表 3.5 顺序表和链表的综合比较.
算法3.3 void InitList_sq(SqList &L,int msize=LIST_INIT_SIZE)
第二章 线性表 线性表是一种最简单的线性结构 线性结构是一个数据元素的有序(次序)集.
第二部分 数据结构—— 用面向对象方法与C++描述.
第二章 线性表 东南大学计算机学院 方效林 本课件借鉴了清华大学殷人昆老师 和哈尔滨工业大学张岩老师的课件.
Presentation transcript:

第二章 线性表 线性表 顺序表 链表 顺序表与链表的比较

线性表 其中,ai 是表中数据元素,n 是表长度。 定义: n(0)个数据元素的有限序列,记作(a1, …ai-1, ai, ai+1,…, an) 其中,ai 是表中数据元素,n 是表长度。 特点: 同一线性表中元素具有相同特性。 相邻数据元素之间存在序偶关系。 除第一个元素外,其他每一个元素有一个且仅有一个直接前驱。 除最后一个元素外,其他每一个元素有一个且仅有一个直接后继。

两集合合并 void union(List &La,List Lb){ La_len=ListLength(La); Lb_len=ListLength(Lb); for(i=1;i<=Lb_len;i++){ GetElem(Lb,i,e); if(!LocateElem(La,e,equal))ListInsert(La,++La_len,e); }

void MergeList(List La,List Lb,List &Lc){ InitList(Lc); i=j=1;k=0; La_len=ListLength(La);Lb_len=ListLength(Lb); while((i<=La_len)&&(j<=Lb_len)){//La和Lb均非空 GetElem(La,i,ai);GetElem(Lb,j,bj); if(ai<=bj) {ListInsert(Lc,++k,ai);++i;} else {ListInsert(Lc,++k,bj);++j;} } while(i<=La_len){ GetElem(La,i++,ai);ListInsert(Lc,++k,ai); while(j<=Lb_len){ GetElem(Lb,j++,bj);ListInsert(Lc,++k,bj); }//MergeList

顺序表 定义:将线性表中的元素相继存放在一个连续的存储空间中。 存储结构:数组。 特点:线性表的顺序存储方式。 存取方式:顺序存取 顺序存储结构示意图 0 1 2 3 4 5 45 89 90 67 40 78

a a+l … a+(i-1)*l … … … a+(n-1)*l idle 顺序表的存储方式: LOC(a i+1) = LOC( a i )+l LOC(a i) = LOC(a1)+(i-1)*l a1 a2 … a i … … … an 1 2 … i … … … n a a+l … a+(i-1)*l … … … a+(n-1)*l idle

顺序表(SeqList)的类型定义 typedef int ListData; typedef struct { #define ListSize 100 //最大允许长度 typedef int ListData; typedef struct { ListData * data; //存储空间基址 int length; //当前元素个数 }

顺序表基本运算 初始化 void InitList ( SeqList & L ) { L.data = ( ListData * ) malloc ( ListSize * sizeof ( ListData ) ); if ( L.data == NULL ) { printf ( “存储分配失败!\n” ); exit (1); } L.length = 0;

按值查找:找x在表中的位置,若查找成功,返回表项的位置,否则返回-1 int Find ( SeqList &L, ListData x ) { int i = 0; while ( i < L.length && L.data[i] != x ) i++; if ( i < L.length ) return i; else return -1; }

int IsIn ( SeqList &L, ListData x ) { int i = 0, found=0; while ( i < L.length &&!found ) if(L.data[i] != x ) i++; else found=1; return found; }

求表的长度 提取函数:在表中提取第 i 个元素的值 return L.length; } int Length ( SeqList & L ) { return L.length; } 提取函数:在表中提取第 i 个元素的值 ListData GetData ( SeqList &L, int i ) { if ( i >= 0 && i < L.length ) return L.data[i]; else printf ( “参数 i 不合理!\n” );

int Next ( SeqList &L, ListData x ) { int i = Find(x); if ( i >=0 && i < L.length-1 ) return i+1; else return -1; } 寻找x的前驱 if ( i >0 && i < L.length ) return i-1;

插入 0 1 2 3 4 5 6 7 25 34 57 16 48 09 63  i 插入 x 50 0 1 2 3 4 5 6 7 25 34 57 50 16 48 09 63  50 顺序表插入时,平均数据移动次数AMN在各表项 插入概率相等时

顺序表的插入 int Insert ( SeqList &L, ListData x, int i ) { //在表中第 i 个位置插入新元素 x if (i < 0 || i > L.length || L.length == ListSize) return 0; //插入不成功 else { for ( int j = L.length; j > i; j-- ) L.data[j] = L.data[j -1]; L.data[i] = x; L.length++; return 1; //插入成功 }

顺序表删除平均数据移动次数AMN在各表项 25 34 57 50 16 48 09 63  16 删除 x 0 1 2 3 4 5 6 7 25 34 57 50 48 09 63  顺序表删除平均数据移动次数AMN在各表项 删除概率相等时

顺序表的删除 int Delete ( SeqList &L, ListData x ) { //在表中删除已有元素 x int i = Find (L, x); //在表中查找 x if ( i >= 0 ) { L.length -- ; for ( int j = i; j < L.length; j++ ) L.data[j] = L.data[j+1]; return 1; //成功删除 } return 0; //表中没有 x

顺序表的应用:集合的“并”运算 void Union ( SeqList &A, SeqList &B ) { int n = Length ( A ); int m = Length ( B ); for ( int i = 0; i < m; i++ ) { int x = GetData ( B, i ); //在B中取一元素 int k = Find (A, x); //在A中查找它 if ( k == -1 ) //若未找到插入它 { Insert ( A, x, n ); n++; } }

void Intersection ( SeqList &A, SeqList &B ) { 集合的“交”运算 void Intersection ( SeqList &A, SeqList &B ) { int n = Length ( A ); int m = Length ( B ); int i = 0; while ( i < n ) { int x = GetData ( A, i ); //在A中取一元素 int k = Find ( B, x ); //在B中查找它 if ( k == -1 ) { Delete ( A, i ); n--; } else i++; //未找到在A中删除它 }

链表(Linked List) 链表是线性表的链接存储表示 单链表 静态链表 循环链表 双向链表

单链表(Singly Linked List) 定义:用一组地址任意的存储单元存放线性表中的数据元素。 存储地址 1 7 13 19 25 31 37 数据域 指针域 ZHANG 13 WANG 1 LI null ZHAO 37 WU 7 ZHOU 19 SUN 25 头指针 31

data link 存储结构:链式存储结构 特点:存储单元可以不连续。 存取方式:顺序存取。 单链表结构 每个元素由结点(Node)构成, 它包括两个 域:数据域Data和指针域Link data link Node 存储结构:链式存储结构 特点:存储单元可以不连续。 存取方式:顺序存取。

单链表的类型定义 typedef char ListData; typedef struct node { //链表结点 ListData data; //结点数据域 struct node * link; //结点链域 } ListNode; typedef ListNode * LinkList; //链表头指针 LinkList first; //链表头指针

newnode->link = first ; 单链表的基本运算 插入(三种情况) 第一种情况:在第一个结点前插入 newnode->link = first ; first = newnode; newnode newnode first first (插入前) (插入后)

newnode->link = p->link; 第二种情况:在链表中间插入 newnode->link = p->link; p->link = newnode; newnode newnode p p (插入前) (插入后)

newnode->link = p->link; 第三种情况:在链表末尾插入 newnode->link = p->link; p->link = newnode; p newnode newnode  p  (插入前) (插入后)

int Insert ( LinkList& first, int x, int i ) { 算法描述 int Insert ( LinkList& first, int x, int i ) { //在链表第 i 个结点处插入新元素 x ListNode * p = first; int k = 0; while ( p != NULL && k < i -1 ) { p = p->link; k++; } //找第 i-1个结点 if ( p == NULL && first != NULL ) { printf ( “无效的插入位置!\n” );//终止插入 return 0; } ListNode * newnode = //创建新结点 (ListNode *) malloc ( sizeof (ListNode) );

newnode->data = x; if ( first == NULL || i == 1 ) { //插入空表或非空表第一个结点之前 newnode->link = first;//新结点成为第一个结点 if(first==NULL)last=newnode;//若是空表,表尾指针指向新结点 first = newnode; } else {//插在表中间或末尾 newnode->link = p->link; if(p->link ==NULL)last=newnode; p->link = newnode; return 1;

删除 在单链表中删除ai结点 p->link = q->link; q = p->link; 删除前 ai-1 ai+1  ai-1 ai ai+1 p q 删除后

int Delete ( LinkList& first, int i ) { ListNode *p, *q; if ( i == 0 ) //删除表中第 1 个结点 { q = first; first = first->link; } else { p = first; int k = 0; while ( p != NULL && k < i-1 ) { p = p->link; k++; } //找第 i-1个结点

if ( p == NULL || p->link == NULL ) {//找不到第 printf ( “无效的删除位置!\n” ); return 0; } else {//删除中间结点或尾结点元素 q = p->link; p->link = q->link; if (q==last) last=p;//删除表尾结点 k= q->data; free ( q ); return k; //取出被删结点数据并释放q

表头结点位于表的最前端,本身不带数据,仅标志表头。 设置表头结点的目的: 简化链表操作的实现。 带表头结点的单链表 表头结点位于表的最前端,本身不带数据,仅标志表头。 设置表头结点的目的: 简化链表操作的实现。 非空表 空表 ^ an a1 first

插入 q->link = p->link; p->link = q; 插入前 插入后 first first p p q ^ first p p q q ^

插入 p p q q

int Insert (LinkList first, ListData x, int i ) { ListNode * p = Locate ( first, i-1 ); if ( p == NULL ) return 0; //参数i值不合理返回0 ListNode * newnode = //创建新结点 (ListNode *) malloc (sizeof (ListNode) ); newnode->data = x; newnode->link = p->link; //链入 p->link = newnode; return 1; }

删除 ^ ^ p q p q q = p->link; p->link = q->link; delete q; 删除前 first first ^ 删除后 first ^ first p q p q (非空表) (空表)

int delete ( LinkList first, int i ) { ListNode * p, * q p = Locate ( first, i-1 ); //寻找第i-1个结点 if ( p == NULL || p->link == NULL) return 0;//i值不合理或空表 q = p->link; p->link = q->link; //删除结点 free ( q ); //释放 return 1; }

前插法建立单链表 从一个空表开始,重复读入数据: 生成新结点 将读入数据存放到新结点的数据域中 将该新结点插入到链表的前端 直到读入结束符为止。 first first ^ q q ^

LinkList createListF ( void ) { char ch; ListNode *q; LinkList head = //建立表头结点 (LinkList) malloc (sizeof (ListNode)); head->link = NULL; while ( (ch = getchar( ) ) != ‘\n’ ) { q = (listNode *) malloc (sizeof(ListNode)); q->data = ch; //建立新结点 q->link = head->link; //插入到表前端 head->link = q; } return head;

后插法建立单链表 ^ ^ ^ ^ 每次将新结点加在链表的表尾; 尾指针r ,总是指向表中最后一个结点,新结点插在它的后面; first r q r

LinkList createListR ( void ) { char ch; LinkList head = //建立表头结点 (LinkList) malloc (sizeof (ListNode)); ListNode *q, *r = NULL; while ( (ch = getchar( ) ) != ‘\n’ ) { q = (listNode *) malloc (sizeof(ListNode)); q->data = ch; //建立新结点 r ->link = q; r =q; //插入到表末端 } r ->link = NULL; return head;

单链表清空 void makeEmpty ( LinkList first ) { ListNode *q; //删去链表中除表头结点外的所有其它结点 ListNode *q; while ( first->link != NULL ) {//当链不空时,循环逐个删去所有结点 q = first->link; first->link = q->link; free( q ); //释放 } last=first;

计算单链表长度 int Length ( LinkList first ) { ListNode *p = first->link; //指针 p 指示第一个结点 int count = 0; while ( p != NULL ) { //逐个结点检测 p = p->link; count++; } return count;

按值查找 ListNode * Find ( LinkList first, ListData value ) { ListNode * p = first->link; //指针 p 指示第一个结点 while ( p != NULL && p->data != value ) p = p->link; return p; }

ListNode * Locate ( LinkList first, int i ) { 按序号查找(定位) ListNode * Locate ( LinkList first, int i ) { //返回表中第 i 个元素的地址 if ( i < 0 ) return NULL; ListNode * p = first; int k = 0; while ( p != NULL && k < i ) { p = p->link; k++; } //找第 i 个结点 if ( k == i ) return p; //返回第 i 个结点地址 else return NULL; }

静态链表 用一维数组描述线性链表 1 2 3 4 5 6 1 ZHANG 2 WANG 3 LI 4 ZHAO 5 WU -1 1 2 3 4 5 6 1 ZHANG 2 WANG 6 LI 5 ZHAO WU -1 CHEN 3 (插入chen,删除zhao)修改后 修改前

定义 const int MaxSize = 100; //静态链表大小 typedef int ListData; typedef struct node { //静态链表结点 ListData data; int link; } SNode; typedef struct { //静态链表 SNode Nodes[MaxSize]; int newptr; //当前可分配空间首地址 } SLinkList;

链表空间初始化 void InitList ( SLinkList SL ) { SL.Nodes[0].link = 1; SL.newptr = 1; //当前可分配空间从 1 开始 //建立带表头结点的空链表 for ( int i = 1; i < MaxSize-1; i++ ) SL.Nodes[i].link = i+1; //构成空闲链接表 SL.Nodes[MaxSize-1].link = -1; //链表收尾 }

在静态链表中查找具有给定值的结点 int Find ( SLinkList SL, ListData x ) { int p = SL.Nodes[0].link; //指针 p 指向链表第一个结点 while ( p != -1 )//逐个查找有给定值的结点 if ( SL.Nodes[p].data != x) p = SL.Nodes[p].link; else break; return p; }

在静态链表中查找第 i 个结点 int Locate ( SLinkList SL, int i ) { if ( i < 0 ) return -1;//参数不合理 int j = 0, p = SL.Nodes[0].link; while ( p != -1 && j < i ) {//循环查找第 i 号结点 p = SL.Nodes[p].link; j++; } if ( i == 0 ) return 0; return p;

在静态链表第 i 个结点处插入一个新结点 int Insert ( SLinkList SL, int i, ListData x ) { int p = Locate ( SL, i-1 ); if ( p == -1 ) return 0; //找不到结点 int q = SL.newptr; //分配结点 SL.newptr = SL.Nodes[SL.newptr].link; SL.Nodes[q].data = x; SL.Nodes[q].link = SL.Nodes[p].link; SL.Nodes[p].link = q; //插入 return 1; }

在静态链表中释放第 i 个结点 int Remove ( SLinkList SL, int i ) { int p = Locate ( SL, i-1 ); if ( p == -1 ) return 0; //找不到结点 int q = SL.Nodes[p].link; //第 i 号结点 SL.Nodes[p].link = SL.Nodes[q].link; SL.Nodes[q].link = SL.newptr; //释放 SL.newptr = q; return 1; }

循环链表 (Circular List) 带表头结点的循环链表 特点:最后一个结点的 link 指针不为NULL,而是指向头结点。只要已知表中某一结点的地址,就可搜寻所有结点的地址。 存储结构:链式存储结构 带表头结点的循环链表 first a0 a1 an-1 (非空表) first (空表)

循环链表的插入

约瑟夫问题 用循环链表求解约瑟夫问题 n 个人围成一个圆圈,首先第2个人从1开始一个人一个人顺时针报数, 报到第m个人,令其出列。然后再从下一个人开始,从1顺时针报数,报到第m个人,再令其出列,…,如此下去, 直到圆圈中只剩一个人为止。此人即为优胜者。 例如 n = 8 m = 3

约瑟夫问题的解法 #include <iostream.h> #include “CircList.h” void Josephus ( int n, int m ) { for ( int i=0; i<n-1; i++ ) { //执行n-1次 for ( int j=0; j<m-1; j++ ) Next ( ); cout << “Delete person ” << getData ( ) << endl; //数m-1个人 Remove ( ); //删去 }

CircList<int> clist; int n, m; void main ( ) { CircList<int> clist; int n, m; cout << “Enter the Number of Contestants?”; cin >> n >> m; for ( int i=1; i<=n; i++ ) clist.insert (i); //形成约 瑟夫环 clist.Josephus (n, m); //解决约瑟夫问题 }

多项式及其相加 在多项式的链表表示中每个结点增加了一个数据成员link,作为链接指针。 优点是: 多项式的项数可以动态地增长,不存在存储溢出问题。 插入、删除方便,不移动元素。

多项式链表的相加 AH = 1 - 10x6 + 2x8 +7x14 BH = - x4 + 10x6 - 3x10 + 8x14 +4x18

Polynomial operator + ( const Polynomial & ah, const Polynomial & bh ) { Term *pa, *pb, *pc, *p; ListIterator<Element> Aiter ( ah.poly ); ListIterator<Element> Biter ( bh.poly ); //建立两个多项式对象 Aiter、 Biter pa = pc = Aiter.First ( ); // pa 检测指针 pb = Biter.First ( ); // pb 检测指针 pa = Aiter.Next ( ); pb = Biter.Next( ); // pa, pb 越过表头结点 delete pb;

while ( Aiter.NotNull ( ) && Biter.NotNull ( ) ) switch ( compare ( pa→exp, pb→exp ) ) { case '=' : pa→coef = pa→coef + pb→coef; p = pb; pb = Biter.Next ( ); delete p; if ( !pa→coef ) { p = pa; pa = Aiter.Next ( ); delete p; } else { pc→link = pa; pc = pa; pa = Aiter.Next ( ); break;

case '<' : pc→next = pb; pc = pb; pb = Biter.Next ( ); break; pc→next = pa; pc = pa; pa = Aiter.Next ( ); } if ( Aiter.NotNull ( ) ) pc→next = pa; else pc→next = pb;

双向链表 (Doubly Linked List) 双向链表结点结构: prior data next 指向直接前驱 指向直接后继 first first 非空表 空表

双向循环链表的定义 typedef int ListData; typedef struct dnode { ListNode data; struct dnode * prior, * next; } DblNode; typedef DblNode * DblList;

建立空的双向循环链表 void CreateDblList ( DblList & first ) { first = ( DblNode * ) malloc ( sizeof ( DblNode ) ); if ( first == NULL ) { print ( “存储分配错!\n” ); exit (1); } first->prior = first->next = first; //表头结点的链指针指向自己 }

计算双向循环链表的长度 int Length ( DblList first ) { //计算带表头结点的双向循环链表的长度 DblNode * p = first->next; int count = 0; while ( p != first ) { p = p->next; count++; } return count; }

双向循环链表的插入 (非空表) p p q q->prior = p; q->next = p->next; p->next = q; q->next->prior = q; 在结点 *p 后插入25 first 31 48 15 p first 31 48 25 15 p q

双向循环链表的插入 (空表) q p q->prior = p; q->next = p->next; p->next = q; q->next->prior = q; 在结点 *p 后插入25 p q first 25

int Insert ( DblList first, int i, ListData x ) { DblNode * p = Locate ( first, i-1 ); //指针定位于插入位置 if ( p == first && i != 1) return 0; DblNode * q = ( DblNode * ) malloc ( sizeof ( DblNode ) ); //分配结点 q->data = x; q->prior = p; p->next->prior = q; //在前驱方向链入新结点 q->next = p->next; p->next = q; //在后继方向链入新结点 return 1; }

双向循环链表的删除 p p->next->prior = p->prior; p->prior->next = p->next; first 31 48 15 p 删除48 first (非空表) 31 15

p->next->prior = p->prior; p->prior->next = p->next; 双向循环链表的删除 first 31 p 删除31 p->next->prior = p->prior; p->prior->next = p->next;

int Remove ( DblList first, int i ) { DblNode * p = Locate ( first, i ); //指针定位于删除结点位置 if ( p == first ) return 0; p->next->prior = p->prior; p->prior->next = p->next; //删除结点 p free ( p ); //释放 return 1; }

顺序表与链表的比较 基于空间的比较 存储分配的方式 顺序表的存储空间是静态分配的 链表的存储空间是动态分配的

顺序表与链表的比较 基于时间的比较 存取方式 顺序表可以随机存取,也可以顺序存取 链表是顺序存取的 插入/删除时移动元素个数 顺序表平均需要移动近一半元素 链表不需要移动元素,只需要修改指针

结 束