·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法

Slides:



Advertisements
Similar presentations
程序设计实习 3月份练习解答
Advertisements

数据结构概论 第2章 线性表 董黎刚 浙江工商大学信电学院
第三章 鏈結串列 Linked List.
第二章 线性表 1 线性表的逻辑结构及其基本操作 2 线性表的顺序存储结构 3 线性表的链式存储结构 4 静态链表 5 应用实例.
第二章 线性表.
第二章 JAVA语言基础.
Chapter 3: Stack.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
單向鏈結串列 Singly Linked Lists.
第2章 线性表 线性结构 是一个数据元素的有序集合。.
走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
佇列 (Queue).
資料結構 第5章 佇列.
親愛的老師您好 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 博碩文化:
Chap 3 堆疊與佇列 Stack and Queue.
第五章 数组和 广义表 数组 稀疏矩阵 广义表.
第11章 运算符重载 什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例.
第七章 搜索结构 静态搜索结构 二叉搜索树 AVL树.
Array & General List.
第2章 线性表(三) 1/.
哈夫曼编码.
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
程序设计期末复习 黎金宁
第三章 C++中的C 面向对象程序设计(C++).
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
cn/~dongeliu/dsa.html 刘 东 信息学院6系 中国科学技术大学
第十章 C高级程序应用—链表* 10.1链表的基本概念 10.2单向链表 10.3双向链表 10.4应用举例.
计算机网络讲义 第5章 批量数据处理—数组 一维数组 排序和查找 二维数组 字符串.
第 3 讲 线性表(一).
第三章 栈和队列.
第二章 线性表.
数据结构与算法
第一章 绪论.
五、链 表 1、单链表 2、双向链表 3、链表应用.
陈海明 副教授 信息学院 计算机系 电子信息类非计算机专业选修课 程序设计实践 陈海明 副教授 信息学院 计算机系
第三章 栈和队列.
資料結構 第4章 堆疊.
第三章 链表 单链表 (Singly Linked List) 循环链表 (Circular List) 多项式及其相加
Chapter6 队列(Queues) The Abstract Data Type
王玲 第 2 章 线性表 王玲 2019/2/25.
10 多載函數 10.1 多載概論 多載一般函數 多載成員函數 10-3
二叉树的遍历.
3.1 线性表及逻辑结构 3.2 线性表的顺序存储 3.3 线性表的链式存储 3.4 链式存储结构的应用
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
常宝宝 北京大学计算机科学与技术系 数据结构(三) 常宝宝 北京大学计算机科学与技术系
第五章 递归与广义表 递归的概念 递归过程与递归工作栈 递归与回溯 广义表.
潘爱民 C++ Overview 潘爱民
程式結構&語法.
第二章 数组 作为抽象数据类型的数组 顺序表 多项式抽象数据类型 稀疏矩阵 字符串 小结.
top b top a a top 空栈 a 进栈 b 进栈 top top e e e top d d d c c c b b b a a
保留字與識別字.
第四章 栈和队列 栈 ( Stack ) 队列 ( Queue ) 优先队列 (Priority Queue) 小结.
字符串 (String) 字符串是 n (  0 ) 个字符的有限序列, 记作 S = “c1c2c3…cn” 其中,S 是串名字
第二章 线性表.
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
第二章 Java语法基础.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第 3 章 类的基础部分 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
十二、堆 堆的定义.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
第三章 线性表 3.1 线性表的类型定义 3.2 顺序存储的线性表 3.3 链式存储的线性表 3.4 有序表 3.5 顺序表和链表的综合比较.
第2章 Java语言基础.
Chapter 2 Entity-Relationship Model
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
Presentation transcript:

·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法 第二章 线性表 ·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法

线性表的定义 空或者只有一个结点。或 1、存在唯一的一个被称之为”第一个“ 的结点。 2、存在唯一的一个被称之为”最后一个“ 的结点。 空或者只有一个结点。或 1、存在唯一的一个被称之为”第一个“ 的结点。 2、存在唯一的一个被称之为”最后一个“ 的结点。 3、除第一个结点之外,每个结点均只有一个前驱结点。 4、除最后一个结点之外,每个结点均只有一个后继结点。 分为以下几大类: ·线性表:通过它们之间的相对位置,确定它们之间的相互关系的线性结构。 e.g: 序列:a1、 a2、 a3…………………an-1、 an ·分类表 ·时间有序表 ·频率有序表 ·序列 结点(数据元素):由多个数据项构成,每个数据项表示该结点的某种性质。 如:学生登记表中的每个学生结点,由学号、姓名、性别、系别…… 等构成。 存放在外存中的结点通常称之为记录。

线性表的ADT ADT 2.1: 线性表List的ADT Element: { xi | xi ElemSet, i=1,2,3,……n, n > 0}; ElemSet为结点集合。 Relation: {<xi, xi+1>|xi,xi+1ElemSet, i=1,2,3,……n-1}, x1为首结点,xn为尾结点 Operations: Constructor 前提: 无或指定List 的规模。 结果: 分配相应空间及初始化。 Clear 前提: 无。 结果: 删除表List 中的所有结点并进行初始化。 IsEmpty 前提: 无 结果: 表List 为空返回True,否则返回False。 IsFull 结果: 表List 为满返回True,否则返回False。

线性表的ADT Length 前提: 无 结果: 返回表List 中的结点个数。 Get 前提: 表List非空且已知结点序号 前提: 无 结果: 返回表List 中的结点个数。 Get 前提: 表List非空且已知结点序号 结果: 返回相应结点的数据值。 Prior 前提: 表List非空,已知结点序号且该结点非首结点。 结果: 返回其直接前驱结点的序号。 Next 前提: 表List非空,已知结点序号且该结点非尾结点 结果: 返回其直接后继结点的序号。 Find 前提: 表List非空,已知结点的数据值。 结果: 查找成功,返回相应结点序号,否则返回查找失败标志 Insert 前提: 已知待插入的数据值以及插入位置。 结果: 插入具有该数据值的结点,表List的结点个数增大1。 Delete 前提: 表List非空,已知被删结点的数据值。 结果: 首先查找相应结点,查找成功则删除该结点,表List的 结点个数将减少1。否则返回删除失败标志。

线性表的顺序存储结构 物理存储位置的计算: ·顺序表示:在物理位置上紧靠在一起。如用数组表示线性表。 ·设第一个结点的存储地址为 LOC(a0), 余类推。设每个结点占用 L 个单元。则: LOC(ai) = LOC(ai-1) + L = LOC(ai-2) + 2L = LOC(ai-i) + i * L = LOC(a0) + i * L a0 a1 ai-1 ai ·随机存取:访问任何一个数据元素或结点花费同样多时间。 an-1

线性表的顺序存储结构 template <class ElemType> class SeqList { private: ElemType * elem; // 顺序表存储数组,存放实际的数据结点。 int length; // 顺序表中的结点个数,亦称表的长度。 int MaxSize; // 顺序表的最大可能的长度。 public: SeqList ( int InitSize ); // 构造函数 ~SeqList ( ); // 析构函数 void Clear( ); // 清空顺序表 bool IsEmpty ( ) const { return ( length = = 0 ); } //表为空返回TRUE,否则返回FALSE。 bool IsFull ( ) const { return (length = =MaxSize) }; // 表是否已经满,满则返回TRUE,否则FALSE。 int Length ( ) const; // 表的长度 ElemType Get ( int i ) const; // 返回第i个结点的值 int Next ( int i ) const; // 若第i个结点的直接后继结点存在,返回其下标, 否则返回 0 int Prior ( int i ) const; // 若第i个结点的直接前驱结点存在,返回其下标,否则返回 0   int Find (ElemType e ) ; // 返回值等于e的结点的序号,无则返回0

线性表的顺序存储结构 template <class ElemType> class SeqList { ……   int Find (ElemType e ) const; // 返回值等于e的结点的序号,无则返回0 int Insert (int i, const ElemType & e ); // 在第i个位置上插入新的结点(值为e),并使原来的第i个结点至最后一个 结点的序号依次加1。插入成功返回1,否则为0 int Delete ( ElemType & e, int i ); // 若第i个结点存在,删除并将其值放入e, // 若i 非法,则删除失败,返回0。 }; 注意:本处惯例,0号单元不用。Length 既是顺序表的当前结点个数,同时又是尾结点的指针。

主要函数的实现:顺序表的创建 25 12 47 99 89 36 template <class ElemType> SeqList<ElemType>::SeqList ( int InitSize ) { // 构造函数 if ( InitSize > 0 ) { elem = new ElemType[ InitSize]; // 申请连续空间,返回空间首地址。 Exception( !elem, ”there is no space in memory”) // 若申请空间失败,则程序中断。 length=0; MaxSize = InitSize-1; } 25 12 47 99 89 36 length

主要函数的实现:查找及其分析 25 12 47 99 89 36 template <class ElemType> int SeqList<ElemType>::Find ( ElemType e ) { // 按照下标从大到小顺序查找值为e的数组结点的下标并将其返回。 // elem[0]做哨兵用,保证即使查找失败,也可以在哨兵位上能找到值e。 elem[0] = e; int i = length; // 初始位置为尾结点所在下标 while (elem[i] != e ) i--; // 不等时继续向前比较,找到返回结点下标,否则返回0。 return i; } 25 12 47 99 89 36 length 成功查找时的平均比较次数:等概率情况, n为表中结点数 ∑ (n-i+1) / n = (n+1)/2 时间复杂性为 O(n)。 1 i=n

主要函数的实现:插入及其分析 template <class ElemType> int SeqList<ElemType>::Insert (int i, const ElemType & e) { //在位置 i 上插入一个值为e的结点,原来的第i个结点变为第 // i+1个结点,其余后继结点序号同样加1,插入成功返回1。 Exception( ( i < 1) || ( i > length+1 ), ”i is not correct .”); // 插入位置i不合法 Exception( MaxSize = = length, ”no space for new item.”); // 存储空间已经满了,无法插入。 //从尾结点起到第i个结点逐个向后移动一个位置 for ( int j = length; j >= i; j--) elem[j+1]=elem[j]; elem[i]=e; // 将要插入的结点值放入第i个结点的位置 length++; // 顺序表结点个数加1 return 1; // 插入成功返回1 } 1 2 3 4 5 6 7 8 12 47 89 36 14 99插入 length

主要函数的实现:插入及其分析 ·插入(插 如之后成为第 i 个结点,注意从第 1 个结点开始) : 1 2 3 4 5 6 7 8 12 47 89 36 14 12 47 89 36 14 12 47 89 36 14 12 47 89 36 14 12 47 99 89 36 14 99插入 ·如图 99 插入之后成为第 3 个结点,移动 5-(3-1) 次。 在一般情况下,插入之后成为第i个结点,移动 n-(i-1)= n-i+1 次。

主要函数的实现:插入及其分析 ·插入后成为第 3 个结点,移动 5-(3-1) 次。 在一般情况下,插入后成为第 i 个结点,移动 n-i+1) 次 插入后成为第 1 个结点,移动 n 次 插入后成为第 i 个结点,移动 n-i+1 次 插入后成为第 n 个结点,移动 1 次。 插入后成为第 n+1 个结点,移动 0 次。 总共 n+1 种情况 ·在长度为 n 的线性表中插入一个结点的平均次数为: ∑(n-i+1)/(n+1) = n/2 时间复杂性为 O(n)。 n+1 i =1

主要函数的实现:删除及其分析 1 2 3 4 5 6 7 8 12 47 89 36 14 template <class ElemType> int SeqList<ElemType>::Delete( ElemType & e, int i ) { // 若第i个结点存在,删除并将其值放入e, 若i 非法,删除失败。 Exception( ( i < 1) || ( i > length ), ”i is illgeal .”); e = elem[i]; // 将第i个结点值首先读出,用于返回。 for (int j=i; j<length; j++) elem[j]=elem[j+1]; // 第i+1个结点到尾结点逐个前移。 length--; // 表长度减1。 return i; // 返回成功标志 i。 } 删除89 length ·如图结点的数据值为 89 的结点删除将移动 5-3 次。 在一般情况下,删除第i个结点,移动 n-i 次。

主要函数的实现:删除及其分析 1 2 3 4 5 6 7 8 12 47 89 36 14 12 47 36 14 12 47 36 14 12 47 36 14 删除

主要函数的实现:删除及其分析 ·删除第 3 个结点,移动 5- 3 次。 在一般情况下,删除第 i 个结点,移动 n-i 次 ∑(n-i)/n = (n-1)/2 时间复杂性为 O(n)。 n i =1 ·另外,通过数据场之值 x 查找结点,代价 O(n)。 查找第 i 个结点,代价O(1)。

线性表的链接存储结构 单链接表:通常用于表示线性结构,如:线性表 · 结点的表示:参照下图所示的情况: Element: 数据场-通常用于保存结 点的数据元素或数据值 Next: 指针场-给出直接后继结点 的地址 Element Next · 单链接表的表示:参照下图所示的情况: 其中 head 是表首指针。 Element Next head 头结点:不是线性表 之中的结点。但增加 此结点后,操作容易。 head A A B B Z ∧ Z ∧

单链接表、双链表和双向循环链表

链表的ADT ADT2.2 链表类 AbsList 的定义。 template <class ElemType> class AbsList { public: AbsList ( ) { }; // 构造函数 virtual ~AbsList ( ) { } // 析构函数 virtual IsEmpty ( ) const = 0; // 判表空吗? virtual IsFull ( ) const = 0; // 判表满吗? virtual void MakeEmpty( ) = 0; // 将表清空。 firiend class AbsListItr< ElemType >; private: AbsList( const AbsList & ) { } // 冻结复制另一链表的构造函数。 };

链表类迭代器类 ADT2.3 链表迭代器类 AbsListItr 的定义。 template <class ElemType> class AbsListItr { public: AbsListItr ( const AbsList< ElemType > & L ) { } //构造函数。 AbsListItr ( const AbsListItr & ); // 通过复制构造当前迭代器 virtual ~ AbsListItr ( ) { } // 析构函数 // 以下函数是基本数据操纵类成员函数。 virtual void Insert( const ElemType & x ) = 0; //插入在当前结点(值为x)之后。 virtual int Remove( const ElemType & x ) = 0; //删除值为x的结点。 virtual int Find( const ElemType & x ) = 0; // 查找值为x的结点。 virtual int IsFound( const ElemType & x ) const = 0; //查找值为x的结点成功否。 // 访问当前结点运算符。 virtual int operator+ ( ) const = 0; // 判当前结点存在吗? virtual const ElemType & operator ( ) ( ) const = 0; // 取当前结点内容。 // 定位运算符及函数。 virtual void Zeroth ( ) = 0; // 定位于链表的首结点之前。 virtual void First ( ) = 0; // 定位于链表的首结点。 virtual void operator ++ ( ) = 0; // 定位于链表的下一个结点。 virtual void operator ++ ( int ) = 0; // 定位于链表的下一个结点。 protected: AbsListItr( ) { } // 冻结无参的构造函数。 }; 请改正书上这行!

单链表结点类 · 结点类的定义: Element: 数据场-通常用于保存结点的数据元素或数据值。 Element Next 程序2.5 单链表结点类。 template <class ElemType> class List; // 单链表类的向前说明。 template <class ElemType> class ListItr; // 单链表迭代器类的向前说明。 template <class ElemType> class ListNode{ friend class List <ElemType>; // 单链表类为其友元类, 便于访问结点类中的私有成员。 friend class ListItr <ElemType>; // 单链表迭代器类为其友元类, 便于访问结点类中的私有成员。 private: ListNode<ElemType> * Next; // 指向下一个结点的指针。 ElemType Element; // 结点数据。 public: ListNode ( const ElemType & E, ListNode< ElemType > * N = NULL ) : Element( E ), Next(N) { } // 构造函数 ListNode( ) : Next( NULL ) { } // 构造函数 ~ListNode ( ) { }; // 析构函数 };

单链表类 · 单链接表类: Element Next 程序2.6: 单链表类。 template <class ElemType> class ListItr; // 单链表迭代器类的向前说明。 template <class ElemType> class List : public AbsList<ElemType> { friend class ListItr <ElemType>; // 单链表迭代器类为其友元类。 private: ListNode<ElemType> * head; // 指向头结点的指针。 public: List( ) { head = new ListNode< ElemType >( ); } ~ List( ) { MakeEmpty( ); delete head; } // 析构函数 const List & operator = ( const List & R ); // 完成复制功能。 int IsEmpty( ) const { return head->Next = = NULL; } int IsFull( ) const { return 0; } void MakeEmpty( ); };

迭代器类 Element Next 迭代器类: 程序2.7: 迭代器类。 template <class ElemType> class ListItr : public AbsListItr<ElemType> { private: ListNode<ElemType> * const head; // 指向头结点的常指针。 ListNode<ElemType> * Current; // 指向当前结点的指针。 public: ListItr( const List<ElemType> & L) : head( L.head ) { Current = L.IsEmpty( ) ? head : head->Next; } ~ ListItr( ) { } // 析构函数 int Find( const ElemType & x ); // 查找值为x的结点,查找成功则使其成为当前结点,并返回True。 int IsFound( const ElemType & x ) const; //查找值为x的结点,查找成功返回 // True,否则返回False;不改变指针Current的值。 void Insert( const ElemType & x ); // 插入成功,新结点成为当前结点。 int Remove( const ElemType & x ); // 删除值为x的结点的操作。

迭代器类 Element Next 迭代器类: 程序2.7: 迭代器类(续)。 ………… int operator + ( ) const { return Current && Current != head; } // 当前结点非空则返回True。 const ElemType & operator ( ) ( ) const; // 取当前结点的数据值。 void operator ++ ( ); // 使当前结点的直接后继结点成为当前结点。 void operator ++ ( int ) { operator ++ ( ); } // 定义为前缀++运算符。 void Zeroth ( ) { Current = head; } // 当前指针指向头结点。 void First( ); // 当前指针指向首结点。 const ListItr & operator=( const ListItr & ); // 赋值运算符。 };

插入操作 · 插入操作的实现:将新结点插入到当前结点(指针Current指向的结点)之后。 A B Current Tmp = new ListNode( ); Tmp->Element = x; x Tmp

插入操作 ·插入操作的实现:将新结点插入到当前结点(指针Current指向的结点)之后。 2. Current->Next = Tmp A B Current 1. Tmp->Next = Current->Next x 注意:1、2 不可颠倒,否则链表将脱链。时间代价: O(1) 可用一个语句取代上述操作, 即:Current->Next = new ListNode(x, Current->Next ); Tmp · 指针 p 和指向的对象的关系: Element Next a b c p · 程序语句: p->next ->next->next

删除操作 ·删除 Current 所指向的结点之后继结点。要知被删结点的前驱结点的地址 Current a b c p p = Current ->Next Current

删除操作 删除 Current 所指向的结点之后继结点。要知被删结点的前驱结点的地址 Current a b c p Current Current->Next = p->Next;

删除操作 删除 Current 所指向的结点之后继结点。要知被删结点的前驱结点的地址 Current a c Current delete p; 注意:必须释放 p ->。时间 O(1)。养成良好的程序设计习惯。

链接存储 vs. 顺序存储 · 和顺序存储的线性表的操作的比较: 插入: O(1) 插入: O(n) 删除: O(1) 删除: O(n) · 和顺序存储的线性表的操作的比较: 插入: O(1) 删除: O(1) FINDith: O(i) 平均 O(n) FINDkey : 平均 O(n) 插入: O(n) 删除: O(n) FINDith: O(1) FINDkey : 平均 O(n) 单链表 顺序存储的线性表

迭代器中基本操作的实现 · 迭代器中基本操作 Find 和 IsFound的实现 template <class ElemType> int ListItr<ElemType> :: Find( const ElemType & x ) { ListNode<ElemType> * Ptr = head->Next; while ( Ptr != NULL && !( Ptr->Element = = x ) ) Ptr = Ptr->Next; if ( Ptr = = NULL ) return 0; Current = Ptr; return 1; } int ListItr<ElemType> :: IsFound( const ElemType & x ) const { while ( Ptr != NULL && !( Ptr->Element = = x) ) Ptr = Ptr->Next; return Ptr != NULL;

迭代器中基本操作的实现 · 在迭代器中,基本操作Insert 和Delete 的实现 template <class ElemType> void ListItr<ElemType> :: Insert( const ElemType & x ) { // 插入操作。 Exception( Current = = NULL, “ The location is illegal!” ); ListNode<ElemType> *p; p = new ListNode<ElemType> ( x, Current->Next); Current = Current->Next = p; // 插入到当前结点之后 } int ListItr<ElemType> :: Remove( const ElemType & x ) { ListNode<ElemType> * Ptr = head; while ( Ptr->Next != NULL && !( Ptr->Next->Element == x) ) Ptr = Ptr->Next; if ( Ptr ->Next = = NULL ) return 0; // 未找到数据值为x的结点,删除失败。 ListNode<ElemType> * P = Ptr->Next; Ptr->Next = Ptr->Next->Next; delete P; Current = head; return 1;

迭代器中基本操作的实现 程序2.8: 类List 的赋值运算符 = 的实现。 template <class ElemType> const List<ElemType> & List<ElemType> :: operator = ( const List<ElemType> & R ) { if ( this = = &R ) return *this; // 同一单链表,不必赋值。 MakeEmpty( ); // 清空单链表。 ListItr<ElemType> Itr( *this ); for ( ListItr<ElemType> Ritr( R ); +Ritr; Ritr++ ) Itr.Insert( Ritr( ) ); // 根据单链表R 的结点数据值,创建新结点,并插入到当前链表。 return *this; }

单向循环链表 带头结点的单向循环链表 1、带头结点的单向循环链表 2、带头结点的单向循环链表的初态 不带头结点的单向循环链表         ……     head 1、带头结点的单向循环链表   2、带头结点的单向循环链表的初态 head 不带头结点的单向循环链表       ……     head 1、不带头结点的单向循环链表 head =NULL 2、不带头结点的单向循环链表的初态

单向循环链表 不带头结点的单向循环链表(使用尾指针) 1、不带头结点的单向循环链表 2、不带头结点的单向循环链表的初态 tail         ……     1、不带头结点的单向循环链表 tail tail =NULL 2、不带头结点的单向循环链表的初态

双链表、双向循环链表 B (1). 带头结点和最后一个结点的双链表 Prior Element Next 初始化       A   B   C           head tail 初始化         head tail (2). 双向循环链表的一种实现方案 Prior Element Next A B C D head head = NULL; 初始化

双链表的删除 · 删除:给出待删结点的地址就可以把它删除。如;删除数据场之值为 a 的结点,地址由 current 给出。 head c a b tail Current head c a b tail 执行: Current ->Prior->Next = current ->Next ; 后 Current head c a b tail 执行: Current ->Next->Prior = Current ->Prior; 后 最后执行:delete Current; 将结点删除。 Current

双链表的插入 · 插入:注意插入次序。如:将数据场为 x 的结点,插在当前结点之后。 head c a b tail Current p x ·p->prior = Current; Current p x ·p->Next = Current ->Next; head tail c a b Current ·Current ->Next->prior = p; p x ·Current ->Next = p;

一元多项式的表示及加法 ·如:多项式: AH = 7+3x+9x8+5x17 BH = 8x+22x7-9x8 Struct Term { float coef; int exp; Term(int c, int e) { coef=c;exp=e;} ………… } ; coef exp link AH ∧ 7 0 3 1 9 8 5 17 BH 8 1 22 7 -9 8 ∧ CH ∧ 7 0 11 1 22 7 5 17

一元多项式的加法 ·如:多项式: AH = 7+3x+9x8+5x17 BH = 8x+22x7-9x8 ; 结果保留在 CH 的单链表之中。 AH ∧ 7 0 3 1 9 8 5 17 BH 8 1 22 7 -9 8 ∧ coef expn Next CH 7 0 ∧ ·算法:指数等:若系数之和为零,则两结点都删除。pa、pb 后移。 否则将相加后的系数、及相应指数送入单链表 C, pa、pb 后移。 pa->指数小:将系数、及相应指数送入单链表 C, pa 后移。 pa->指数大:将链表 B系数、及相应指数送入单链表 C, pb 后移。 注意: 将任何一个多项式的多余部分,插入在单链表 C 之后。

一元多项式的加法 ·如:多项式: AH = 7+3x+9x8+5x17 BH = 8x+22x7-9x8 ; 结果保留在 CH 的单链表之中。 AH ∧ 7 0 3 1 9 8 5 17 BH 8 1 22 7 -9 8 ∧ coef expn Next CH 7 0 11 1 ∧ ·算法:指数等:若系数之和为零,则两结点都删除。pa、pb 后移。 否则将相加后的系数、及相应指数送入单链表 C, pa、pb 后移。 pa->指数小:将系数、及相应指数送入单链表 C, pa 后移。 pa->指数大:将链表 B系数、及相应指数送入单链表 C, pb 后移。 注意: 将任何一个多项式的多余部分,插入在单链表 C 之后。

一元多项式的加法 ·如:多项式: AH = 7+3x+9x8+5x17 BH = 8x+22x7-9x8 ; 结果保留在 CH 的单链表之中。 AH ∧ 7 0 3 1 9 8 5 17 BH 8 1 22 7 -9 8 ∧ coef expn Next CH 7 0 11 1 22 7 ∧ ·算法:指数等:若系数之和为零,则两结点都删除。pa、pb 后移。 否则将相加后的系数、及相应指数送入单链表 C, pa、pb 后移。 pa->指数小:将系数、及相应指数送入单链表 C, pa 后移。 pa->指数大:将链表 B系数、及相应指数送入单链表 C, pb 后移。 注意: 将任何一个多项式的多余部分,插入在单链表 C 之后。

一元多项式的加法 ·如:多项式: AH = 7+3x+9x8+5x17 BH = 8x+22x7-9x8 ; 结果保留在 CH 的单链表之中。 AH ∧ 7 0 3 1 9 8 5 17 BH 8 1 22 7 - 9 8 ∧ coef expn Next CH 7 0 11 1 22 7 ∧ ·算法:指数等:若系数之和为零,则两结点都删除。pa、pb 后移。 否则将相加后的系数、及相应指数送入单链表 C, pa、pb 后移。 pa->指数小:将系数、及相应指数送入单链表 C, pa 后移。 pa->指数大:将链表 B系数、及相应指数送入单链表 C, pb 后移。 注意: 将任何一个多项式的多余部分,插入在单链表 C 之后。

一元多项式的加法 一元多项式的表示及相加; ·如:多项式: AH = 7+3x+9x8+5x17 BH = 8x+22x7-9x8 ; 结果保留在 CH 的单链表之中。 AH ∧ 7 0 3 1 9 8 5 17 BH 8 1 22 7 -9 8 ∧ coef expn Next CH ∧ 7 0 11 1 22 7 5 17 ·算法:指数等:若系数之和为零,则两结点都删除。pa、pb 后移。 否则将相加后的系数、及相应指数送入单链表 C, pa、pb 后移。 pa->指数小:将系数、及相应指数送入单链表 C, pa 后移。 pa->指数大:将链表 B系数、及相应指数送入单链表 C, pb 后移。 注意: 将任何一个多项式的多余部分,插入在单链表 C 之后。 ·注意:迭代器是一种“指针”抽象。

一元多项式的加法 程序的实现 main( ) { Term R(-1,-1); // 多项式输入的结束标志。 Polynomial<Term > a(R), b(R), c; cin >> a >> b; // 读入 2 个多项式,通过对 >> 重载实现。 c = a; // 多项式 a 并不破坏,将其值送入 c 。 c + b; // 完成多项式c、b相加,结果保存在多项式 c 之中。 cout << c; // 将多项式 c 输出。 return 0; }

一元多项式的加法 template <class ElemType> Polynomial<ElemType> & Polynomial<ElemType> :: operator + (const Polynomial<ElemType> & T ) { ElemType elemA, elemB; Polynomial< ElemType > C; ListItr<ElemType > ItrA(poly); ListItr<ElemType > ItrB(T. poly); ListItr<ElemType > ItrC(C. poly); for ( ; +ItrA && +ItrB; ) { elemA = ItrA( ); elemB = ItrB( ); switch ( compare( elemA, elemB)) { case ‘=’: elemA += elemB; if ( !Is_Empty( elemA ) ) ItrC.Insert(elemA); ++ItrA; ++ItrB; break; case ‘>’ : ItrC.Insert(elemB); ++ItrB; break; case ‘<’ : ItrC.Insert(elemA); ++ItrA; break; } if ( +ItrA ) for ( ; +ItrA; ++ItrA ) { elemA = ItrA( ); ItrC.Insert(elemA); } else for ( ; +ItrB; ++ItrB ) { elemB = ItrB( ); ItrC.Insert(elemB); } *this = C; return *this; ∧ 3 1 9 8 5 17 pa pc ∧ 13 12 5 27 pb p

应用:静态链表 · 静态链表的实现: 用于没有动态存储分配功能的语言,如 FORTRAN、COBOL等;当然也可用于C/c++ 等高级语言。缺点:必须预估存区的大小,造成浪费。优点:插、删操作省时。 · e.g: 设集合 A = (c,b,e,g,f,d) 和 B = (a,b,n,f) 。求集合运算 (A-B) ∪ (B-A) 的结 果。 解: A-B = (c,e,g,d); B-A = (a,n)。 (A-B) ∪ (B-A) = (c,e,g,d,a,n)。 程序执行步骤: 1、将用作存储空间的数组的所有单元分配至可利用空间表(也称:空闲栈或备 用链(保存未被使用的结点的单链表)。 2、建立集合 A 的静态链表。 3、逐个输入集合 B 的元素,同时查找 A 的静态链表有无该元素。有则删 除,无则插入该结点。 4、集合 B 的元素输入完毕,则在原集合 A 的静态链表中得到了集合运算 (A-B) ∪ (B-A)的结果。

应用:静态链表 1、将用作存储空间的数组的所有单元分配至空闲栈或备用链。 data cur data cur space[0] 1 2 space[2] 3 space[3] 4 space[4] 5 space[5] 6 space[6] 7 space[7] 8 space[8] 9 space[9] 10 space[10] 11 space[11] -1

应用:静态链表 1、将用作存储空间的数组的所有单元分配至空闲栈或备用链。 · 备用链经初始化之后的情况:注意此处的地址是下标地址。 1 2 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 9 data cur 9 10 11 · 为了形象起见,和动态分配的单链表表示相似,备用链初 始化之后通常表示成以下形式。 10 11 -1 1 2 3 4 5 6 7 8 data cur 9 10 11 -1 void InitSpace_SL(SLinkList & Space) { for ( i=0; i < MAXSIZE -1; ++i ) space[i].cur = i+1; space[MAXSIZE-1] = -1; } int Malloc_SL(SLinkList &Space) { i = space[0].cur; if ( space[0].cur != -1) space[0].cur = space[i].cur; return i; } int free_SL(SLinkList &Space, int k) { space[k].cur = space[0].cur; space[0].cur = k; }

应用:静态链表 2、建立集合 A 的静态链表: · 集合 A 的静态链表的初始化。 1 工作链: s 备用链: 2 3 4 5 6 7 8 备用链: 2 3 4 5 6 7 8 data cur 9 10 11 -1

应用:静态链表 2、建立集合 A 的静态链表: · 集合 A 的静态链表:在输入元素 c 之后。 1 2 工作链: s c 备用链: r 3 备用链: r 3 4 5 6 7 8 data cur 9 10 11 -1

应用:静态链表 2、建立集合 A 的静态链表: · 集合 A 的静态链表:在输入元素 b 之后。 1 2 3 工作链: s c b 备用链: 备用链: r 4 5 6 7 8 data cur 9 10 11 -1

应用:静态链表 2、建立集合 A 的静态链表: · 集合 A 的静态链表:在输入元素 e 之后。 1 2 3 4 工作链: s c b e 备用链: r 5 6 7 8 data cur 9 10 11 -1

应用:静态链表 2、建立集合 A 的静态链表: · 集合 A 的静态链表:在输入元素 g 之后。 1 2 3 4 5 工作链: s c b e g 备用链: r 6 7 8 9 10 11 -1 data cur

应用:静态链表 2、建立集合 A 的静态链表: · 集合 A 的静态链表:在输入元素 f 之后。 1 2 3 4 5 6 工作链: s c b e g f 备用链: r 7 8 9 10 11 -1 data cur

应用:静态链表 2、建立集合 A 的静态链表: · 集合 A 的静态链表:在输入元素 d 之后。 1 2 3 4 5 6 7 工作链: s c b e g f d 备用链: r 8 9 10 11 -1 data cur

应用:静态链表 3、逐个输入集合 B 的元素。 · 输入 a, 查找 A 的静态链表。a 不在,插入。 1 2 3 4 5 6 7 工作链: s c b e g f d r 8 a 备用链: 9 10 11 -1 data cur

应用:静态链表 3、逐个输入集合 B 的元素。 · 输入 b, 查找 A 的静态链表。b 在,在表中删除它。注意:回收单元至备用链。 1 2 4 5 6 7 8 工作链: s c e g f d a r 备用链: 3 9 10 11 b -1 data cur

应用:静态链表 3、逐个输入集合 B 的元素。 · 输入 n, 查找 A 的静态链表。n 不在,插入。 1 2 4 5 6 7 8 工作链: s c e g f d n r 3 a 备用链: 9 10 11 -1 data cur

应用:静态链表 3、逐个输入集合 B 的元素。 · 输入 f, 查找 A 的静态链表。f 在,在表中删除它。注意:回收单元至备用链。 1 2 4 5 7 8 工作链: s c e g d a r 3 n 备用链: 6 9 10 11 f -1 data cur

应用:静态链表 4、集合 B 的元素输入完毕,则在原集合 A 的静态链表 中得到了集合运算 (A-B) ∪ (B-A)的结果 1 2 4 5 7 8 工作链: s c e g d a r 3 n 备用链: 6 9 10 11 f -1 data cur 时间复杂性:和集合 A、B 的长度之积成正比。

应用:稀疏矩阵 2. 链表的应用:稀疏矩阵-只有少数非 0 矩阵元素的情况。 0 1 2 3 4 5 6 ·稀疏矩阵: 2. 链表的应用:稀疏矩阵-只有少数非 0 矩阵元素的情况。 0 1 2 3 4 5 6 ·稀疏矩阵: 0 0 11 0 0 13 0 12 0 0 0 0 0 14 0 -4 0 0 0 -8 0 0 0 0 0 0 0 0 0 -9 0 0 0 0 0 1 2 3 4 5 ·稀疏矩阵的结点结构: F 表示本结点表示非 0 矩阵元素 head row col down value right F 2 1 - 4 指向本行值为-8的结点 F 表示本结点表示非 0 矩阵元素 指向本列值为-9的结点 F 6 7 7 6、7 表示稀疏矩阵共有6行、7列 特殊结点 headnode 指向表头H0 7 表示稀疏矩阵共有 7个非0元素。

应用:稀疏矩阵 2. 链表的应用:稀疏矩阵-只有少数非 0 矩阵元素的情况。 0 1 2 3 4 5 6 ·稀疏矩阵: 2. 链表的应用:稀疏矩阵-只有少数非 0 矩阵元素的情况。 0 1 2 3 4 5 6 ·稀疏矩阵: 0 0 11 0 0 13 0 12 0 0 0 0 0 14 0 -4 0 0 0 -8 0 0 0 0 0 0 0 0 0 -9 0 0 0 0 0 1 2 3 4 5 ·稀疏矩阵的行、列表头结点结构:0行,0列表头结点共用一个表头结点,余类推。 Head next down right T next down 列表头:next: 给出下一个列表头结点地址 down:给出本列中第一个非0矩阵元素结点地址 T right 行表头:right:给出本行中第一个非0矩阵元素结点地址

应用:稀疏矩阵 2. 链表的应用;稀疏矩阵-只有少数非 0 矩阵元素的情况,稀疏矩阵正交链表表示 1 2 3 4 5 6 H指针数组: 2. 链表的应用;稀疏矩阵-只有少数非 0 矩阵元素的情况,稀疏矩阵正交链表表示 1 2 3 4 5 6 H指针数组: headnode F 6 7 7 T T T T T T T T F 0 2 11 F 0 5 13 T F 1 0 12 F 1 6 14 T F 2 1 - 4 F 2 5 - 8 0 0 11 0 0 13 0 12 0 0 0 0 0 14 0 -4 0 0 0 -8 0 0 0 0 0 0 0 0 0 -9 0 0 0 0 0 T T T F 5 1 - 9