数据结构——线性表
概念介绍
线性表是一种最简单常用的基本数据结构,线性表在计算机中可以用顺序存储和链式存储 两种存储结构表示。用顺序存储结构表示的线性表为顺序表,用链式存储结构表示的线性表为链表 。
线性表是由n(n>=0)个数据元素所构成的有限序列,通常表示为(a0,a1,…,ai,…an-1),i表示位序号,n表示线性表的表长。所以我们所熟知的数组就是一种线性表。
线性表的抽象类型描述
1、什么是抽象类型描述?
抽象数据类型包含一般数据类型的概念,但含义比一般数据类型更广、更抽象。抽象数据类型通常由编程者定义数据以及对数据的操作。
2、一般有以下几种基本操作:
clear():将一个线性表置空
isEmpty():判断线性表是否已空,为空返回true,否则返回false
length():求线性表中的元素个数并返回其值
get(i):读取并返回线性表中的第i个数据元素的值
insert(i,x):将值为x的元素插入到线性表第i个元素之前
remove(i):删除并返回线性表的第i个元素
indexOf(x):返回线性表首次出现指定元素的位序号,若不存在该元素则返回-1
display():输出线性表中各个元素的值
线性表的顺序存储
1、定义:在上面已经提及,这里补充一点:顺序存储是用一组地址连续的存储单元依次存放线性表中各个数据元素的存储结构。其实顺序表就是一维数组
2、特点:
(1)线性表在逻辑上相邻的元素,物理存储上也相邻
(2)存储密度高,需要预先分配足够大的空间
(3)便于随机存取
(4)不便于插入和删除操作
线性表的链式存储
1、链表特点:链表中每一个结点包含存放数据元素值得数据域和存放指向逻辑上相邻结点的指针域。
2、单链表:当一个结点只有一个指针域,成为单链表。
3、结点类描述:
public class Node<T>{
public T data;
public Node<T> next;
public Node() {
this(null,null);
}
public Node(T data) {
this(data,null);
}
public Node(T data,Node<T> next) {
this.data = data;
this.next = next;
}
}
4、单链表类描述:
public class linklist<T>{
public Node<T> head;
public linklist() {
head = new Node<T>();
}
//尾插法
public void create1(T data){
Node<T> p = head;
while(p.next!=null){
p = p.next;
}
Node<T> newnode = new Node<T>(data);
p.next = newnode;
}
//头插法
public void create2(T data){
Node<T> newnode = new Node<T>(data);
newnode.next = head.next;
head.next = newnode;
}
public void clear() {//置成空表
head.data = null;
head.next = null;
}
public boolean isEmpty(){//判断是否为空链表
return head.next ==null;
}
public int length(){//链表长度
Node<T> p = head.next;
int length = 0;
while(p!=null) {
length++;
p = p.next;
}
return length;
}
public Object get(int i){//返回第i个
Node<T> p = head.next;
int j = 0;//计数器
while(p!=null&&j<i) {
p = p.next;
++j;
}
if(j>i||p==null) {
System.out.print("第"+i+"个元素不存在");
}
return p.data;
}
public void insert(int i,T x){//第i个位置前插入值为x的元素
Node<T> p = head;
int j = -1;//计数器
while(p!=null&&j<i-1) {
p = p.next;
++j;
}
if(j>i-1||p==null) {
System.out.print("第"+i+"个元素不存在");
}
Node<T> s = new Node<T>(x);
s.next = p.next;
p.next = s;
}
public void remove(int i){//删除第i个
Node<T> p = head;
int j=-1;
while(p.next!=null&&j<i-1) {
p = p.next;
++j;
}
if(j>i-1||p.next ==null) {
System.out.print("删除位置不合法");
}
p.next = p.next.next;
}
public int indexOf(T x){//返回首次出现x的位序号,没有则返回-1
Node<T> p = head.next;
int index = 0;
while(!p.data.equals(x)&&p!=null) {
p = p.next;
++index;
}
if(p!=null) {
return index;
}
else {
return -1;
}
}
public void display(){//输出各个数据的值
Node<T> node = head.next;
while(node!=null) {
System.out.print(node.data+" ");
node = node.next;
}
System.out.println();
}
}
单链表类的描述中包含了单链表的两种创建方法:头插法和尾插法
这两种方法顾名思义,头插法是在head后插入新的结点构成链表,尾插法为在链表的最后一个结点后插入新结点构成链表
其他的方法为线性表的一些基本操作
5、其他链表
循环链表,双向链表
6、顺序表与链表比较
顺序表适合用于需要经常访问数据元素的,适用于变化小的,且变化频率低的,空间利用率高,适用实现静态的线性表,不易扩充,可高效随机存取
链表适用于需要经常插入删除的,空间利用率低,只能顺序存取,适用实现动态的线性表