一.线性表的定义
线性表(Linear
List)是由n(n≥0)个类型相同的数据元素a0,a1,…,an-1组成的有限序列。
LinearList=(a0,a1,…,an-1)
①n是线性表的元素个数,称为线性表的长度。n=0时LinearList为空表。
②数据元素ai(0≤i≤n-1)只是个抽象符号,其具体含义在不同情况下可以不同。
ADT List<T>//线性表抽象数据类型,数据元素的数据类型为T
boolean isEmpty() //判断线性表是否为空
int size() //返回线性表长度
void set(int i, T x) //设置第i号元素为x
String toString() //所有元素的描述字符串
int insert(int i, T x) //插入x作为第i号元素
int insert(T x) //在线性表最后插入x元素
T remove(int i) //删除第i号元素
void clear() //删除所有元素
int search(T key) //查找与key相等元素
boolean contains(T key) //判断是否包含key元素
int insertDifferent(T x) //插入不重复元素
T remove(T key) //删除与key相等元素
boolean equals(Object obj) //比较是否相等
void addAll(List<T> list) //添加list所有元素
1.线性表的顺序存储
(1)顺序表类(SeqList.java)
(2)顺序表操作的效率分析
时间复杂度:O(1)
-
-
-
- isEmpty()
- length()
- get(int i)
- set(int i, T x)
-
-
时间复杂度是O(n)
-
-
-
- insert(int i, T x)
- remove(int i)
-
-
-
(3).顺序表比较相等
2.线性表的链式表示和实现
(1)线性表的链式存储结构
-
- 用链式存储结构实现的线性表称为链表。
- 链表的结点的个数称为链表的长度,长度为0时为空表。
(2)单链表
1. 单链表结点类
public class Node<T> //单链表结点类,T指定结点的元素类型
{
public T data; //数据域,存储数据元素
public Node<T> next; //地址域,引用后继结点
public Node(T data, Node<T> next) //构造结点,data指定数据元素,next指定后继结点
{
this.data = data; //T对象引用赋值
this.next = next; //Node<T>对象引用赋值
}
public Node()
{
this(null, null);
}
public String toString() //返回结点数据域的描述字符串
{
return this.data.toString();
}
}
- Node类是“自引用的类”。它的成员变量next的数据类型是Node类自己。自引用的类指一个类声明包含一个引用当前类的对象的成员变量。
- 结点Node分为两部分,一部分是data域,另一部分是Node域,
-
- data域存放需要存储的数据,类型是T类型的。
- 而Node域存放下一个结点的地址,类型是Node本身。目的是指向下一个结点。
- Node<T> head=null;当head==null时,是空单链表
2. 单链表的基本操作
-
-
-
-
-
-
-
单链表的遍历操作
Node<T> p = head;
while (p!=null)
{ p.data.toString() //执行访问p结点的相关操作
p = p.next;
} - 单链表的插入操作
①空表插入/头插入
-
if (head == null) //空表插入 head = new Node<T>(x, null); else //头插入 { Node<T> p = new Node<T>(x, null); p.next = head; head = p; }
上述所有代码可合并为:head = new Node<T>(x, head);
-
-
-
-
-
-
② 中间插入/尾插入
Node<T> p = new Node<T>(x, null);
p.next = front.next; //p的后继是front的后继
front.next = p; //p作为front的后继
上述所有代码可合并为:
front.next = new Node<T>(x, front.next);
-
-
-
-
-
-
-
- 单链表的删除操作
-
-
-
-
-
-
①
头删除
head = head.next;
②中间/尾删除
if (front.next!=null)
front.next = front.next.next ;
3. 带头结点的单链表
头结点的作用是,使所有链表(包括空表)的头指针非空,则对单链表的插入、删除操作不需要区分操作位置。
头插入和头删除操作不会改变head指针
带头结点的单链表类(SinglyList.java)
public class SinglyList<T>
{
public Node<T> head; //头指针
public SinglyList() //构造空表
public SinglyList(T[] values)
public boolean isEmpty()
public T get(int i) //返回第i个元素
public void set(int i, T x) //设置第i个元素为x
public int size() //长度
public String toString
public Node<T> insert(int i, T x)
//插入x作为第i个元素
public Node<T> insert(T x) //尾插入
public T remove(int i) //删除第i个元素
public void clear() //删除所有元素
}
4. 单链表操作的效率分析
-
-
-
-
-
-
- isEmpty()方法的时间复杂度是O(1)。
- size()、toString()等,遍历单链表,O(n)。
- get(i)和set(i),遍历部分单链表, O(n),不是随机存取结构。
- insert(i,x)和remove(i),查找i,O(n)。
-
-
-
-
-
5. 单链表的浅拷贝与深拷贝(不要求)
6. 排序单链表(不要求)
7.
循环单链表
(CirSinglyList.java)
public class CirSinglyList<T>
{
public Node<T> head; //头指针
public CirSinglyList() //构造空表
{
this.head = new Node<T>(); //创建头结点
this.head.next = this.head; //构成环形
}
public boolean isEmpty() //判空
{ return this.head.next==this.head;
}
public String toString()
{ //遍历,循环条件改变了
for (Node<T> p=this.head.next; p!=this.head; p=p.next)
}
}