线性结构
线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列;
线性表的基本组成为:数组,单项链表,双向链表;
数组
数组有上界和下界,数组的元素在上下界内是连续的;
比如存储一个整数的数组定义为:
int[] arr = {10,20,30,40,50};
数组的特点是:数据是连续的;随机访问速度快;
数组中稍微复杂一点的是多维数组和动态数组.对于C语言而言,多维数组本质上也是通过一位数组实现的;
至于动态数组,是指数组的容量能动态增长的数组;
对于C语言而言,若要提供动态数组,需要手动实现;
而对于C++而言,STL提供了Vector;
对于Java而言,Collection集合中提供了ArrayList和Vector;
单向链表
单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针;
单链表的示意图如下:
表头为空,表头的后继节点是"节点10"(数据为10的节点),"节点10"的后继节点是"节点20"(数据为20的节点),...
单链表删除节点
删除"节点30"
删除之前:"节点20"的后继节点为"节点30",而"节点30"的后继节点为"节点40";
删除之后:"节点20"的后继节点为"节点40";
单链表添加节点
在"节点10"与"节点20"之间添加"节点15";
添加之前:"节点10"的后继节点为"节点20";
添加之后:"节点10"的后继节点为"节点15",而"节点15"的后继节点为"及诶单20";
双向链表
双向链表(双链表)时候链表的一种;和单链表一样,双链表也是由节点组成的,它的每个数据节点中都有俩个指针,分别指向直接后继和直接前驱;所以,从双向链表中的任意一个节点开始,都可以很方便的访问它的前驱节点和后继节点;一般我们都够着双向循环链表;
双链表的示意图如下:
表头为空,表头的后继节点为"节点10"(数据为10的节点);
"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前驱节点是"节点10";
"节点20"的后继节点是"节点30","节点30"的前驱节点是"节点20";...;
末尾节点的后继节点是表头;
双链表删除节点
删除"节点30"
删除之前:"节点20"的后继节点为"节点30","节点30"的前驱节点为"节点20";
"节点30"的后继节点为"节点40","节点40"的前驱节点为"节点30";
删除之后:"节点20"的后继节点为"节点40","节点40"的前驱节点为"节点20";
双链表添加节点
在"节点10"与"及诶单20"之间添加"节点15";
添加之前:"节点10"的后继节点为"节点20","节点20"的前驱节点为"节点10";
添加之后:"节点10"的后继节点为"节点15","节点15"的前驱节点为"节点10";
"节点15"的后继节点为"节点20","节点20"的前驱节点为"节点15";
下面演示一下双链表的实现,只介绍Java语言的三种实现
双链表类(DoubleLink.java)
/*** Java 实现的双向链表。
* 注:java自带的集合包中有实现双向链表,路径是:java.util.LinkedList
**/
public class DoubleLink{//表头
private DNodemHead;//节点个数
private intmCount;//双向链表“节点”对应的结构体
private class DNode{publicDNode prev;publicDNode next;publicT value;publicDNode(T value, DNode prev, DNode next) {this.value =value;this.prev =prev;this.next =next;
}
}//构造函数
publicDoubleLink() {//创建“表头”。注意:表头没有存储数据!
mHead = new DNode(null, null, null);
mHead.prev= mHead.next =mHead;//初始化“节点个数”为0
mCount = 0;
}//返回节点数目
public intsize() {returnmCount;
}//返回链表是否为空
public booleanisEmpty() {return mCount==0;
}//获取第index位置的节点
private DNode getNode(intindex) {if (index<0 || index>=mCount)throw newIndexOutOfBoundsException();//正向查找
if (index <= mCount/2) {
DNode node =mHead.next;for (int i=0; i
node=node.next;returnnode;
}//反向查找
DNode rnode =mHead.prev;int rindex = mCount - index -1;for (int j=0; j
rnode=rnode.prev;returnrnode;
}//获取第index位置的节点的值
public T get(intindex) {returngetNode(index).value;
}//获取第1个节点的值
publicT getFirst() {return getNode(0).value;
}//获取最后一个节点的值
publicT getLast() {return getNode(mCount-1).value;
}//将节点插入到第index位置之前
public void insert(intindex, T t) {if (index==0) {
DNode node = new DNode(t, mHead, mHead.next);
mHead.next.prev=node;
mHead.next=node;
mCount++;return;
}
DNode inode =getNode(index);
DNode tnode = new DNode(t, inode.prev, inode);
inode.prev.next=tnode;
inode.next=tnode;
mCount++;return;
}//将节点插入第一个节点处。
public voidinsertFirst(T t) {
insert(0, t);
}//将节点追加到链表的末尾
public voidappendLast(T t) {
DNode node = new DNode(t, mHead.prev, mHead);
mHead.prev.next=node;
mHead.prev=node;
mCount++;
}//删除index位置的节点
public void del(intindex) {
DNode inode =getNode(index);
inode.prev.next=inode.next;
inode.next.prev=inode.prev;
inode= null;
mCount--;
}//删除第一个节点
public voiddeleteFirst() {
del(0);
}//删除最后一个节点
public voiddeleteLast() {
del(mCount-1);
}
}
测试程序(DlinkTest.java)
/*** Java 实现的双向链表。
* 注:java自带的集合包中有实现双向链表,路径是:java.util.LinkedList
**/
public classDlinkTest {//双向链表操作int数据
private static voidint_test() {int[] iarr = {10, 20, 30, 40};
System.out.println("\n----int_test----");//创建双向链表
DoubleLink dlink = new DoubleLink();
dlink.insert(0, 20); //将 20 插入到第一个位置
dlink.appendLast(10); //将 10 追加到链表末尾
dlink.insertFirst(30); //将 30 插入到第一个位置//双向链表是否为空
System.out.printf("isEmpty()=%b\n", dlink.isEmpty());//双向链表的大小
System.out.printf("size()=%d\n", dlink.size());//打印出全部的节点
for (int i=0; i
System.out.println("dlink("+i+")="+dlink.get(i));
}private static voidstring_test() {
String[] sarr= {"ten", "twenty", "thirty", "forty"};
System.out.println("\n----string_test----");//创建双向链表
DoubleLink dlink = new DoubleLink();
dlink.insert(0, sarr[1]); //将 sarr中第2个元素 插入到第一个位置
dlink.appendLast(sarr[0]); //将 sarr中第1个元素 追加到链表末尾
dlink.insertFirst(sarr[2]); //将 sarr中第3个元素 插入到第一个位置//双向链表是否为空
System.out.printf("isEmpty()=%b\n", dlink.isEmpty());//双向链表的大小
System.out.printf("size()=%d\n", dlink.size());//打印出全部的节点
for (int i=0; i
System.out.println("dlink("+i+")="+dlink.get(i));
}//内部类
private static classStudent {private intid;privateString name;public Student(intid, String name) {this.id =id;this.name =name;
}
@OverridepublicString toString() {return "["+id+", "+name+"]";
}
}private static Student[] students = newStudent[]{new Student(10, "sky"),new Student(20, "jody"),new Student(30, "vic"),new Student(40, "dan"),
};private static voidobject_test() {
System.out.println("\n----object_test----");//创建双向链表
DoubleLink dlink = new DoubleLink();
dlink.insert(0, students[1]); //将 students中第2个元素 插入到第一个位置
dlink.appendLast(students[0]); //将 students中第1个元素 追加到链表末尾
dlink.insertFirst(students[2]); //将 students中第3个元素 插入到第一个位置//双向链表是否为空
System.out.printf("isEmpty()=%b\n", dlink.isEmpty());//双向链表的大小
System.out.printf("size()=%d\n", dlink.size());//打印出全部的节点
for (int i=0; i
System.out.println("dlink("+i+")="+dlink.get(i));
}
}public static voidmain(String[] args) {
int_test();//演示向双向链表操作“int数据”。
string_test(); //演示向双向链表操作“字符串数据”。
object_test(); //演示向双向链表操作“对象”。
}
}
运行结果
1 ----int_test----
2 isEmpty()=false
3 size()=3
4 dlink(0)=30
5 dlink(1)=20
6 dlink(2)=10
7
8 ----string_test----
9 isEmpty()=false
10 size()=3
11 dlink(0)=thirty12 dlink(1)=twenty13 dlink(2)=ten14
15 ----object_test----
16 isEmpty()=false
17 size()=3
18 dlink(0)=[30, vic]19 dlink(1)=[20, jody]20 dlink(2)=[10, sky]