《数据结构( Java版)(第 3版)》
第 2 章 线性表• 2.1 线性表抽象数据类型• 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现
2.4 线性表的应用:多项式的表示及运算
《数据结构( Java版)(第 3版)》
目的和要求• 目的:实现线性表抽象数据类型。• 内容:将线性表的顺序存储结构和链式存储结构
实现分别封装成顺序表类、单链表类、循环 双链表类等,比较这两种实现的特点以及各 种基本操作算法的效率。
• 要求:理解线性表抽象数据类型,掌握顺序和链式 存储结构实现线性表的方法。
• 重点:顺序表、单链表、循环双链表等线性表的设 计训练。
• 难点:使用指针实现链式存储结构,通过指针操作 改变结点间的链接关系。
• 实验:掌握单链表的遍历、插入、删除、复制等操 作算法,熟悉循环单链表、双链表和循环双 链表的结构和基本操作。掌握 MyEclipse 集
成开发环境的程序调试技术。
《数据结构( 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> // 单链
表类
《数据结构( Java版)(第 3版)》
2.2 线性表的顺序表示和实现
1. 线性表的顺序存储结构
ciaLocaLoc i )()( 0
《数据结构( 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
《数据结构( Java版)(第 3版)》
4. 顺序表的删除操作
3. 顺序表的插入操作
《数据结构( Java版)(第 3版)》
【例 2.1 】 使用顺序表类求解约瑟夫环问题。
element
A
B
0
C
1
2
len-1
5
len
list
3D
Enull…
nullelement.length-1
《数据结构( Java版)(第 3版)》
顺序表的静态特性很好,动态特性很差,具体说明如下。① 顺序表元素的物理存储顺序直接反映线性表元素的逻
辑顺序,顺序表是一种随机存取结构。 get()、 set() 方法时间复杂度是 O(1) 。
② 插入和删除操作效率很低。如果在各位置插入元素的概率相同,则有
5. 顺序表操作的效率分析
n
i
n
ii nO
nnn
nin
npin
00
)(22
)1(
1
1)(
1
1)(
《数据结构( Java版)(第 3版)》
6. 顺序表的浅拷贝与深拷贝 一个类的拷贝构造方法声明格式如下: 类 ( 类 对象 )
( 1 )顺序表的浅拷贝public SeqList(SeqList<T> list)// 浅拷贝构造方法{
this.element = list.element;
// 数组引用赋值,两个变量共用一个数组,错误 this.len = list.len;
}
《数据结构( 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
《数据结构( 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
《数据结构( Java版)(第 3版)》
7. 顺序表比较相等 两个顺序表相等是指,它们各对应元素相等
并且长度相同。
《数据结构( Java版)(第 3版)》
2.3 线性表的链式表示和实现
2.3.1 线性表的链式存储结构
2.3.2 单链表
2.3.3 双链表
《数据结构( 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
《数据结构( 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 单链表
《数据结构( 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
《数据结构( Java版)(第 3版)》
如果语句 p=p.next 写成p.next=p
《数据结构( 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);
《数据结构( 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);
《数据结构( Java版)(第 3版)》
如果上述后两条语句次序颠倒,则产生错误
Node<T> q = new Node<T>(x, null);p.next = q; q.next = p.next;
《数据结构( Java版)(第 3版)》
4. 单链表的删除操作 ① 头删除head = head.next;
② 中间 / 尾删除if (p.next!=null) p.next = p.next.next;
《数据结构( Java版)(第 3版)》
5. 带头结点的单链表
(a)空单链表 (b)头插入,不改变head
head
x
a0
q
p
(c)头删除,不改变head
heada0 a1
p
∧head
头结点
∧…
an-1 ∧…
an-1
《数据结构( 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 ∧
《数据结构( 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) 。
《数据结构( 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
《数据结构( Java版)(第 3版)》
7. 提高单链表操作效率的措施 public boolean append(T x){ return insert(this.length(), x);
// 需遍历单链表两次,效率较低}return insert(Integer.MAX_VALUE, x);
// 遍历一次
《数据结构( 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
《数据结构( Java版)(第 3版)》
例 2.3 求整数单链表的平均值。
《数据结构( 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
《数据结构( Java版)(第 3版)》
8. 单链表的浅拷贝与深拷贝
public SinglyLinkedList(SinglyLinkedList<T> list) // 拷贝构造函数,浅拷贝
{ this.head = list.head; // 导致两个引用变量指向同一个结点}
《数据结构( Java版)(第 3版)》
8. 单链表的深拷贝
《数据结构( Java版)(第 3版)》
9.单链表比较相等两条单链表相等是指,它们各对应元素相
等并且长度相同。
《数据结构( 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
《数据结构( Java版)(第 3版)》
11. 循环单链表
《数据结构( 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∧∧
《数据结构( 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
②①
《数据结构( 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
②①
《数据结构( 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
《数据结构( Java版)(第 3版)》
3. 循环双链表
《数据结构( Java版)(第 3版)》
4. 排序循环双链表
《数据结构( Java版)(第 3版)》
2.4 线性表的应用:多项式的表示及运算
2.4.1 一元多项式的表示及运算
2.4.2 二元多项式的表示及运算
《数据结构( 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
《数据结构( 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
《数据结构( 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 ) 多项式单链表
《数据结构( Java版)(第 3版)》
( 3 ) 多项式类① 多项式类 Polynomial 声明及相加运算
《数据结构( Java版)(第 3版)》
【例 2.6 】 一元多项式的表示及相加运算。
《数据结构( 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
《数据结构( Java版)(第 3版)》
③ 比较两个多项式是否相等public boolean equals(Object obj)
// 比较两个多项式是否相等{
return this==obj || obj instanceof Polynomial && this.list.equals(((Polynomial)obj).list);
}
《数据结构( 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
《数据结构( Java版)(第 3版)》
线性表接口和类的层次关系 LList
线性表接口
SinglyLinkedList单链表类
SeqList顺序表类
SortedSinglyLinkedList排序单链表类
实现
SortedDoublyLinkedList排序循环双链表类
CirDoublyLinkedList循环双链表类
继承 继承
PolySLinkedList多项式排序单链表类
继承
实现 实现