链表结构
链式存储结构是基于指针实现,我们把一个数据元素和一个指针成为节点
链式存储结构是用指针把相互直接关联的结点(即直接前驱节点或直接后继节点)链接起来。 链式存储结构的线性表成为链表
链表类型
根据链表的构造方式的不同可以分为:
1单向链表
2单向循环链表
3 双向循环链表
单链表结构
1单链表是构成链表的每个结点之哟袷指向直接后继结点的指针。
2表示方法和单链表中每个节点的结构
-----------------------------
| 数据元素域 | 指针域 |
-----------------------------
或者
-----------------------------
| element | next |
-----------------------------
单链表有带头结点结构和不带头结点结构两种。我们把指向单链表的指针成为单链表的头指针。
头指针所指向的不存放数据元素的第一个结点称作头结点。 存放第一个数据元素的结点乘坐第一个数据元素结点,或称首元结点。
单链表定义可知,线性表要求允许再任意位置进行插入和删除。当选用带头结点的单链表时,插入和删除操作的实现方法比不带头结点单链表的实现方法简单
设置头指针用head表示,在单链表中任意结点(但不是第一个数据元素结点)前插入一个新结点的方法。算法实现时,首先要把插入位置定位在要插入结点的前一个结点位置,然后把s表示的新结点插入单链表中
不带头结点的单链表,如果插入元素不在第一个结点之前插入,则如上图:在单链表非第一个结点前插入结点过程
要在第一个数据元素结点前插入一个新结点,若采用不带头结点的单链表结构,则结点插入后,头指针head就要等于新插入结点s,这和在非第一个数据元素结点前插入结点时的情况不同。另外,还有一些不同情况需要考虑。因此,算法对这两种情况就要分别设计实现方法。
而如果采用带头结点的单链表结构,算法实现时,p指向头结点,改变的是p指针的next指针的值,而头指针head的值不变。因此,算法实现方法比较简单。在带头结点单链表中第一个数据元素结点前插入一个新结点的过程如图所示。
单链表是由一个一个结点组成的,因此,要设计单链表类,必须先设计结点类。结点类的成员变量有两个:一个是数据元素,另一个是表示下一个结点的对象引用(即指针)。
设计操作:
1.头结点的初始化
2.非头结点的构造
3.获取该结点指向的下个结点
4.设置该结点指向的下个结点
5.设置该结点的数据
6.获取该结点的数据
单链表类的成员变量至少要有两个:
一个是头指针; 一个是单链表中的数据元素个数。但是,如果再增加一个表示单链表当前结点位置的成员变量,则有些成员函数的设计将更加方便。
单链表的效率分析
在单链表的任何位置上插入数据元素的概率相等时,在单链表中插入一个数据元素时比较数据元素的平均次数为:
删除单链表的一个数据元素时比较数据元素的平均次数为:
因此,单链表插入和删除操作的时间复杂度均为O(n)。另外,单链表取数据元素操作的时间复杂度也为O(n)。
顺序表的主要优点是支持随机读取,以及内存空间利用效率高;顺序表的主要缺点是需要预先给出数组的最大数据元素个数,而这通常很难准确作到。当实际的数据元素个数超过了预先给出的个数,会发生异常。另外,顺序表插入和删除操作时需要移动较多的数据元素。
和顺序表相比,单链表的主要优点是不需要预先给出数据元素的最大个数。另外,单链表插入和删除操作时不需要移动数据元素。
单链表的主要缺点是每个结点中要有一个指针,因此单链表的空间利用率略低于顺序表的。另外,单链表不支持随机读取,单链表取数据元素操作的时间复杂度为O(n);而顺序表支持随机读取,顺序表取数据元素操作的时间复杂度为O(1)。
代码实现
一LinkList.java //单向链表类 public class LinkList implements List { Node head; //头指针 Node current;//当前结点对象 int size;//结点个数 //初始化一个空链表 public LinkList() { //初始化头结点,让头指针指向头结点。并且让当前结点对象等于头结点。 this.head = current = new Node(null); this.size =0;//单向链表,初始长度为零。 } //定位函数,实现当前操作对象的前一个结点,也就是让当前结点对象定位到要操作结点的前一个结点。 public void index(int index) throws Exception { if(index <-1 || index > size -1) { throw new Exception("参数错误!"); } //说明在头结点之后操作。 if(index==-1) return; current = head.next; int j=0;//循环变量 while(current != null&&j<index) { current = current.next; j++; } } @Override public void delete(int index) throws Exception { // TODO Auto-generated method stub //判断链表是否为空 if(isEmpty()) { throw new Exception("链表为空,无法删除!"); } if(index <0 ||index >size) { throw new Exception("参数错误!"); } index(index-1);//定位到要操作结点的前一个结点对象。 current.setNext(current.next.next); size--; } @Override public Object get(int index) throws Exception { // TODO Auto-generated method stub if(index <-1 || index >size-1) { throw new Exception("参数非法!"); } index(index); return current.getElement(); } @Override public void insert(int index, Object obj) throws Exception { // TODO Auto-generated method stub if(index <0 ||index >size) { throw new Exception("参数错误!"); } index(index-1);//定位到要操作结点的前一个结点对象。 current.setNext(new Node(obj,current.next)); size++; } @Override public boolean isEmpty() { // TODO Auto-generated method stub return size==0; } @Override public int size() { // TODO Auto-generated method stub return this.size; } } 二//List.java
//线性表接口 public interface List { //获得线性表长度 public int size(); //判断线性表是否为空 public boolean isEmpty(); //插入元素 public void insert(int index,Object obj) throws Exception; //删除元素 public void delete(int index) throws Exception; //获取指定位置的元素 public Object get(int index) throws Exception; }
三 Node.java
//结点类
public class Node {
Object element; //数据域
Node next; //指针域
//头结点的构造方法
public Node(Node nextval)
{
this.next = nextval;
}
//非头结点的构造方法
public Node(Object obj,Node nextval)
{
this.element = obj;
this.next = nextval;
}
//获得当前结点的后继结点
public Node getNext()
{
return this.next;
}
//获得当前的数据域的值
public Object getElement()
{
return this.element;
}
//设置当前结点的指针域
public void setNext(Node nextval)
{
this.next = nextval;
}
//设置当前结点的数据域
public void setElement(Object obj)
{
this.element = obj;
}
public String toString()
{
return this.element.toString();
}
}
四//Test.java
public class Test {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
LinkList list = new LinkList();
for(int i=0;i<10;i++)
{
int temp = ((int)(Math.random()*100))%100;
list.insert(i, temp);
System.out.print(temp+" ");
}
list.delete(4);
System.out.println("\n------删除第五个元素之后-------");
for(int i=0;i<list.size;i++)
{
System.out.print(list.get(i)+" ");
}
}
}
"C:\Program Files\Java\jdk1.8.0_192\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2018.1.2\lib\idea_rt.jar=53313:D:\Program Files\JetBrains\IntelliJ IDEA 2018.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_192\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\rt.jar;C:\Users\Administrator\Desktop\D383C实战应用Java算法分析与设计(链表、二叉树、哈夫曼树、图、动态规划、HashTable算法)\04.单向链表以及单向链表的应用\资料\code\LinkListDemo\out\production\LinkListDemo" Test 99 82 30 28 27 44 93 12 50 10 ------删除第五个元素之后------- 99 82 30 28 44 93 12 50 10 Process finished with exit code 0