Transcript
Page 1: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

第 2 章 线性表• 2.1 线性表抽象数据类型• 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现

2.4 线性表的应用:多项式的表示及运算

Page 2: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

目的和要求• 目的:实现线性表抽象数据类型。• 内容:将线性表的顺序存储结构和链式存储结构

实现分别封装成顺序表类、单链表类、循环 双链表类等,比较这两种实现的特点以及各 种基本操作算法的效率。

• 要求:理解线性表抽象数据类型,掌握顺序和链式 存储结构实现线性表的方法。

• 重点:顺序表、单链表、循环双链表等线性表的设 计训练。

• 难点:使用指针实现链式存储结构,通过指针操作 改变结点间的链接关系。

• 实验:掌握单链表的遍历、插入、删除、复制等操 作算法,熟悉循环单链表、双链表和循环双 链表的结构和基本操作。掌握 MyEclipse 集

成开发环境的程序调试技术。

Page 3: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2.1 线性表的抽象数据类型LinearList=(a0, a1,…, an- 1)

public interface LList<T>{ // 线性表接口,泛型参数 T 表示数据元素的数据类型 boolean isEmpty(); // 判断线性表是否空 int length(); // 返回线性表长度 T get(int i); // 返回第 i( i≥0 )个元素 void set(int i, T x); // 设置第 i 个元素值为 x void insert(int i, T x); // 插入 x 作为第 i 个元素 void append(T x); // 在线性表最后插入 x 元素 T remove(int i); // 删除第 i 个元素并返回被删除对象 void removeAll(); // 删除线性表所有元素 T search(T key); // 查找,返回首次出现的关键字为 key 元素}public class SeqList<T> implements LList<T> // 顺序表

类public class SinglyLinkedList<T> implements LList<T> // 单链

表类

Page 4: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2.2 线性表的顺序表示和实现

1. 线性表的顺序存储结构

ciaLocaLoc i )()( 0

Page 5: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

public class SeqList<T> implements LList<T>

{ // 顺序表类,实现线性表接口

protected Object[] element; // 对象数组 protected int len; // 顺序表长度,记载元素个数}

2. 顺序表类

element

A

B

0

C

1

2

len-1

5

len

list

3D

Enull…

nullelement.length-1

Page 6: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

4. 顺序表的删除操作

3. 顺序表的插入操作

Page 7: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

【例 2.1 】 使用顺序表类求解约瑟夫环问题。

element

A

B

0

C

1

2

len-1

5

len

list

3D

Enull…

nullelement.length-1

Page 8: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

顺序表的静态特性很好,动态特性很差,具体说明如下。① 顺序表元素的物理存储顺序直接反映线性表元素的逻

辑顺序,顺序表是一种随机存取结构。 get()、 set() 方法时间复杂度是 O(1) 。

② 插入和删除操作效率很低。如果在各位置插入元素的概率相同,则有

5. 顺序表操作的效率分析

n

i

n

ii nO

nnn

nin

npin

00

)(22

)1(

1

1)(

1

1)(

Page 9: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

6. 顺序表的浅拷贝与深拷贝 一个类的拷贝构造方法声明格式如下: 类 ( 类 对象 )

( 1 )顺序表的浅拷贝public SeqList(SeqList<T> list)// 浅拷贝构造方法{

this.element = list.element;

// 数组引用赋值,两个变量共用一个数组,错误 this.len = list.len;

}

Page 10: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

执行拷贝构造方法SeqList<String> listb = new

SeqList<String>(lista);

(a)浅拷贝,lista.element与listb.element引用同一个数组 (b)执行lista.remove(4);删除元素导致错误

A

B

C

5lista

D

Enull

5listb

A

B

C

null

4lista

D

null

5listb

elementlen elementlen

elementlenelementlen

Page 11: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

( 2 )顺序表的深拷贝

(a)listb.element申请数组存储空间,对象赋值,导致对应数组元素引用相同实例

A B C

5lista

D E

null

5listb null

(b)申请数组存储空间,创建对象

A B C

5lista

D E

null

5listb null

A B C D E

elementlen

elementlen

elementlen

elementlen

Page 12: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

7. 顺序表比较相等 两个顺序表相等是指,它们各对应元素相等

并且长度相同。

Page 13: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2.3 线性表的链式表示和实现

2.3.1 线性表的链式存储结构

2.3.2 单链表

2.3.3 双链表

Page 14: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2.3.1 线性表的链式存储结构

a0 a1 an-1 ∧…

(a)单链表

ai …

pred data next

(b)双链表

ai ∧head

a0 ai+1 an-1…∧ … ai-1

data nexthead

ai-1 ai+1

Page 15: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

1. 单链表结点类 public class Node<T> // 单链表结点类{ public T data; // 数据域,保存数据

元素 public Node<T> next; // 地址域,引用后继结点}

Node<String> p,q;p=new Node<String>("A", null ); q=new Node<String>("B", null ); p.next=q;

2.3.2 单链表

Page 16: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2. 单链表的遍历操作

Node<T> p = head;while (p!=null) {System.out.print(p.data.toString()+"

"); // 执行访问 p 结点的相关操作 p = p.next;}

p(a)空单链表

head==null

(b)单链表

a0 a1 an-1 ∧… …

data nexthead

ai

Page 17: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

如果语句 p=p.next 写成p.next=p

Page 18: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

3. 单链表的插入操作 ( 1 )空表插入 / 头插入

if (head == null) // 空表插入 head = new Node<T>(x, null); else // 头插入{ Node<T> q = new Node<T>(x, null); q.next = head; head = q;

} 即head = new Node<T>(x, head);

Page 19: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

( 2 )中间插入 / 尾插入

Node<T> q = new Node<T>(x, null);q.next = p.next;//q 的后继结点应是 p 的原后继结点p.next = q; //q 作为 p 的后继结点即 p.next = new Node<T>(x, p.next);

Page 20: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

如果上述后两条语句次序颠倒,则产生错误

Node<T> q = new Node<T>(x, null);p.next = q; q.next = p.next;

Page 21: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

4. 单链表的删除操作 ① 头删除head = head.next;

② 中间 / 尾删除if (p.next!=null) p.next = p.next.next;

Page 22: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

5. 带头结点的单链表

(a)空单链表 (b)头插入,不改变head

head

x

a0

q

p

(c)头删除,不改变head

heada0 a1

p

∧head

头结点

∧…

an-1 ∧…

an-1

Page 23: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

【例 2.2 】 采用单链表求解约瑟夫环问题。

start

(a)5个结点的单链表,从start开始计数,第一次删除结点B

(e)一个结点的单链表

i

(b)再删除结点D

(c)再删除结点A

(d)再删除结点E

headA B E ∧

data next

DC

headA C ∧ED

i

headA C ∧E

i

i

headC E ∧

headC ∧

Page 24: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

6. 单链表操作的效率分析

1. isEmpty() 方法的时间复杂度是 O(1) 。2. length() 方法要遍历单链表,时间复杂度是

O(n) 。 3. get(i)和 set(i) 方法的时间复杂度是 O(n) ,

不是随机存取结构。 4. insert(i,x)和 remove(i) 时间复杂度是

O(n) 。

Page 25: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

1. 在 p 结点之前插入结点 q

2. 删除结点 p 要寻找其前驱结点 front

front

xq

a0 ai-1 ai an-1 ∧… …

p

head

front

ai+1ai-1 ai an-1 ∧… …

p

head

Page 26: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

7. 提高单链表操作效率的措施 public boolean append(T x){ return insert(this.length(), x);

// 需遍历单链表两次,效率较低}return insert(Integer.MAX_VALUE, x);

// 遍历一次

Page 27: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

作用于顺序表的时间复杂度是 O(n) ,但作用于单链表的时间复杂度则是

public String toString(){ String str="("; if (this.length()!=0) { for(int i=0; i<this.length()-1; i++) str += this.get(i).toString()+", "; str += this.get(this.length()-1).toString(); } return str+")";}

)( 2nO

Page 28: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

例 2.3 求整数单链表的平均值。

Page 29: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

【例 2.4 】 单链表逆转。p succfront==null

(b)循环中,使p.next指向前驱结点front,front、p、succ各向后移动一个结点

(a)初始,设置p指向第1个结点,front指向p的前驱,succ指向p的后继

p==null

(c)循环结束后已逆转的单链表

headA B ∧DC

headA ∧ B ∧DC

p succfront

headA ∧ B DC

front

Page 30: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

8. 单链表的浅拷贝与深拷贝

public SinglyLinkedList(SinglyLinkedList<T> list) // 拷贝构造函数,浅拷贝

{ this.head = list.head; // 导致两个引用变量指向同一个结点}

Page 31: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

8. 单链表的深拷贝

Page 32: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

9.单链表比较相等两条单链表相等是指,它们各对应元素相

等并且长度相同。

Page 33: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

10. 排序单链表

(f)排序单链表

p==null

(a)空单链表

head∧41

(b)插入结点41

head

5

∧41

q

front p

q

front

(c)插入结点5

q

front

q

p==null

(d)插入结点67,尾插入

front p

(e)插入结点41,插入在等值结点之后

head1 5 412619 97 ∧6741

∧head

head5 41 67 ∧

head5 41 67 ∧

41

Page 34: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

11. 循环单链表

Page 35: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2.3.3 双链表1. 双链表结构

p = p.next.pred = p.pred.next

(a)空双链表 p

head∧

pred data next

(b)双链表

ai ∧a0 ai+1 an-1…… ai-1

head∧∧

Page 36: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2. 双链表的插入和删除操作(1)插入在 p 结点之前插入值为 x 结点

q = new DLinkNode<T>(x, p.pred, p);

p.pred.next = q;p.pred = q;

p

pred data next

∧a0 an-1…a1

head

xq

②①

Page 37: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

在 p 结点之后插入值为 x 结点

q = new DLinkNode<T>(x, p, p.next); //当 p.next==null 时,尾插入

if (p.next!=null) p.next.pred = q; // 中间插入时执行p.next = q;

p

pred data next

∧a0 an-1…a1

head

xq

②①

Page 38: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

( 2 )双链表的删除操作

p.pred.next = p.next; //有 p.pred!=null

if (p.next!=null) p.next.pred = p.pred;

p

head∧

pred data next

ai ∧ai+1 an-1…… ai-1

Page 39: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

3. 循环双链表

Page 40: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

4. 排序循环双链表

Page 41: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2.4 线性表的应用:多项式的表示及运算

2.4.1 一元多项式的表示及运算

2.4.2 二元多项式的表示及运算

Page 42: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2.4.1 一元多项式的表示及运算

m

i

ii

mmm xaxaxaxaaxA

0

2210)(

n

i

ii

nnn xbxbxbxbbxB

0

2210)(

),max(

0

)()()(nm

i

iiinm xbaxBxA

Page 43: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

1. 一元多项式的顺序存储结构

(b)存储系数为0的项,各项数组下标同指数,查找时间为O(1)(a)不存储系数为0的项,查找各项时间为O(n)

6

7

8

9

0

2

0

-7

0

1

2

4

7

x指数系数

9

2

-1

1

-9

2

-7

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

x指数系数

5

2

-1

1

0

-9

0

0

1

2

3

4

5

顺序表数组 顺序表数组element

5

len

list

element

5

len

list

9742 7292)( xxxxxxAn

Page 44: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2. 一元多项式的链式存储结构

head

系数coef x指数exp

2 0

data next

-1 1项TermX 1 2 -9 4 2 7 -7 9

9742 7292)( xxxxxxAn

( 1 ) 一元多项式的项类( 2 ) 多项式单链表

Page 45: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

( 3 ) 多项式类① 多项式类 Polynomial 声明及相加运算

Page 46: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

【例 2.6 】 一元多项式的表示及相加运算。

Page 47: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

② 多项式深度拷贝及应用

系数coef x指数exp

2 0

data next

-1 1项TermX 1 2 -9 4 2 7 -7 9

2 0 -1 1项TermX 1 2 -9 4 2 7 -7 9

poly.list.head

this.list.head

Page 48: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

③ 比较两个多项式是否相等public boolean equals(Object obj)

// 比较两个多项式是否相等{

return this==obj || obj instanceof Polynomial && this.list.equals(((Polynomial)obj).list);

}

Page 49: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

2.4.2 二元多项式的表示及运算

( 1 ) 二元多项式的项类 TermXY( 2 ) Polynomial 可表示二元多项式 ( 3 ) PolySLinkedList<T> 类的作用

3224 9263),( yxyyxxxyxP

2156362),,( 43342352362310 yzzyxzyxzyxzyxzyxzyxP

coef exp

2 0

data next

-1 1项TermXY 1 2 -9 4 2 8 -7 9

dpoly.list.head

exp_y

0 1 2 1 3 3

Page 50: 第02章  线性表(java版)

《数据结构( Java版)(第 3版)》

线性表接口和类的层次关系 LList

线性表接口

SinglyLinkedList单链表类

SeqList顺序表类

SortedSinglyLinkedList排序单链表类

实现

SortedDoublyLinkedList排序循环双链表类

CirDoublyLinkedList循环双链表类

继承 继承

PolySLinkedList多项式排序单链表类

继承

实现 实现


Recommended