假设 : 有两个 集合 a 和 b 分别用两个 线性表 la 和 lb...

24
假假 : 假假假集集 A 集 B 假假假假假 集集集 LA 集 LB 假假 假假 假假假假假 ,: 假假假假假假假假假假假假集集集 集集集集集 A A∪B

Upload: lula

Post on 19-Mar-2016

428 views

Category:

Documents


12 download

DESCRIPTION

例. 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B 。. 上述问题可演绎为:. 要求对线性表作如下操作: 扩大线性表 LA ,将 存在于线性表 LB 中 而 不存在于线性表 LA 中 的数据元素 插入到线性表 LA 中 去。. 操作步骤:. 1 . 从线性表 LB 中依次察看每个数据元素 ;. Get(LB, i, x). 2 . 依值在线性表 LA 中进行查访 ;. Locate(LA, x). 3 . 若不存在,则插入。. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

假设 :有两个集合 A 和 B 分别用两个线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A B∪ 。

Page 2: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

要求对线性表作如下操作:扩大线性表 LA ,将存在于线性表LB 中而不存在于线性表 LA 中的数据元素插入到线性表 LA 中去。

上述问题可演绎为:

Page 3: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

1 .从线性表 LB 中依次察看每个数据元素 ;

2 .依值在线性表 LA 中进行查访 ;

3 .若不存在,则插入。

Get(LB, i, x)

Locate(LA, x)

Insert(LA, n+1, x)

操作步骤:

Page 4: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

x=Get(Lb, i); if (!Locate(La, x) ) Insert(La, ++La_len, x);

void union(List &La, List Lb) { La_len = Length(La); Lb_len = Length(Lb);

for (i = 1; i <= Lb_len; i++) {

}} // union

Page 5: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

静态链表结构 静态链表结构 利用数组定义,运利用数组定义,运算算过程中存储空间大小不变过程中存储空间大小不变

分配节点:分配节点: j = avil; avil = A[avil].link;释放节点: 释放节点: A[i].link = avil; avil = i;

Page 6: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

循环链表 循环链表 ((Circular ListCircular List))

Page 7: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

循环链表是单链表的变形。循环链表是单链表的变形。循环链表最后一个结点的循环链表最后一个结点的 linklink 指针指针不为 不为 0 (0 (NULLNULL)) ,而是指向了表的,而是指向了表的前端。前端。为简化操作,在循环链表中往往加为简化操作,在循环链表中往往加入表头结点。入表头结点。循环链表的特点是:只要知道表中循环链表的特点是:只要知道表中某一结点的地址,就可搜寻到所有某一结点的地址,就可搜寻到所有其他结点的地址。其他结点的地址。

Page 8: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

循环链表的示例循环链表的示例

带表头结点的循环链表带表头结点的循环链表

Page 9: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

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

Page 10: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

例如 例如 n n = 8 = 8 mm = 3 = 3

Page 11: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

约瑟夫问题的解法约瑟夫问题的解法#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 ( ); // 删去 }}

Page 12: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

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); // 解决约瑟夫问题}

Page 13: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

在多项式的链表表示中每个结点增在多项式的链表表示中每个结点增加了一个数据成员加了一个数据成员 linklink ,作为链接,作为链接指针。指针。优点是:优点是:

– 多项式的项数可以动态地增长,不多项式的项数可以动态地增长,不存在存储溢出问题。存在存储溢出问题。– 插入、删除方便,不移动元素。插入、删除方便,不移动元素。

多项式及其相加多项式及其相加

Page 14: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

多项式多项式 ((polynomialpolynomial)) 类的链表定义类的链表定义struct Term { int coef; int exp; void Init ( int c, int e ) { coef = c; exp = e; }};

class Polynomial { List<Term> poly; friend Polynomial operator + (const Polynomial &, const Polynomial &); };

Page 15: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

多项式链表的相加多项式链表的相加AH = 1 - 10x6 + 2x8 +7x14

BH = - x4 + 10x6 - 3x10 + 8x14 +4x18

Page 16: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

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 = p= Biter.First ( ); // pb 检测指针 pa = Aiter.Next ( ); pb = Biter.Next; // pa, pb 越过表头结点 delete p;

Page 17: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

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;

Page 18: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

case ‘>' : pc→next = pb; pc = pb;

pb = Biter.Next ( ); break; case ‘<' :

pc→next = pa; pc = pa; pa = Aiter.Next ( ); break;

} if ( Aiter.NotNull ( ) ) pc→next = pa; else pc→next = pb;}

Page 19: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

双向链表 双向链表 ((Doubly Linked ListDoubly Linked List)) 双向链表是指在前驱和后继方向都能游历双向链表是指在前驱和后继方向都能游历

(( 遍历遍历 )) 的线性链表。的线性链表。 双向链表每个结点结构:双向链表每个结点结构:

前驱方向前驱方向 后继方向后继方向 双向链表通常采用带表头结点的循环链表形双向链表通常采用带表头结点的循环链表形式。式。

llLLiinnkk((左左链链指指针针 ))

ddaattaa((数数据据 ))

rrLLiinnkk((右右链链指指针针 ))

Page 20: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

结点指向结点指向p ==p == pp→→lLinklLink→→rLink == prLink == p→→rLinkrLink→→lLinklLink

非空表非空表 空表 空表

Page 21: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

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

顺序表的存储空间是静态分配的顺序表的存储空间是静态分配的链表的存储空间是动态分配的链表的存储空间是动态分配的

存储密度 存储密度 = = 结点数据本身所占的存储结点数据本身所占的存储量量 // 结点结构所占的存储总量结点结构所占的存储总量顺序表的存储密度 顺序表的存储密度 = 1= 1链表的存储密度 链表的存储密度 < 1< 1

Page 22: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

顺序表与链表的比较顺序表与链表的比较基于时间的比较基于时间的比较 存取方式存取方式

顺序表可以随机存取,也可以顺序存取顺序表可以随机存取,也可以顺序存取链表是顺序存取的链表是顺序存取的

插入插入 // 删除时移动元素个数删除时移动元素个数顺序表平均需要移动近一半元素顺序表平均需要移动近一半元素链表不需要移动元素,只需要修改指针链表不需要移动元素,只需要修改指针若插入若插入 // 删除仅发生在表的两端,宜采删除仅发生在表的两端,宜采用带尾指针的循环链表用带尾指针的循环链表

Page 23: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

线性表小结主要介绍了如下一些基本概念:线性表:一个线性表是 n≥0 个数据元素 a0 , a1 ,

a2 ,…, an-1 的有限序列。线性表的顺序存储结构:在计算机中用一组地址连续的存储单元依次存储线性表的各个数据元素,称作线性表的顺序存储结构。线性表的链式存储结构:线性表的链式存储结构就是用一组任意的存储单元——结点(可以是不连续的)存储线性表的数据元素。表中每一个数据元素,都由存放数据元素值的数据域和存放直接前驱或直接后继结点的地址(指针)的指针域组成。

Page 24: 假设 : 有两个 集合 A 和 B 分别用两个 线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合 A = A∪B

循环链表:循环链表 (Circular Linked List) 是将单链表的表中最后一个结点指针指向链表的表头结点,整个链表形成一个环,从表中任一结点出发都可找到表中其他的结点。双向链表:双向链表中,在每一个结点除了数据域外,还包含两个指针域,一个指针( next )指向该结点的后继结点,另一个指针( prior )指向它的前驱结点。除上述基本概念以外,学生还应该了解:线性表的基本操作(初始化、插入、删除、存取、复制、合并)、顺序存储结构的表示、线性表的链式存储结构的表示、一元多项式 Pn(x) , Josephus问题。