赞
踩
今天来谈谈链表
数组与链表分别属于线性表的两种基本存储结构:顺序存储结构和链式存储结构。
顺序存储结构:用一段地址连续的存储单元依次存储线性表的数据元素。
链式存储结构:地址可以连续也可以不连续的存储单元存储数据元素。
链式存储结构包括单链表,双链表,循环链表。
链表优劣势:使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,检索时遍历需要从头开始导致效率低。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。
单向链表:
单向链表只有一个指针域,在整个节点中数据域用来存储数据元素,指针域用于指向下一个具有相同结构的节点。
要实现链表首先定义节点类,有数据域(存储数据,类型自定)+引用域(存储下一个节点,用于节点链接)
public class Node {
private Object data;
private Node next;
//无参构造 public Node(){
}
//有参构造 public Node(Object data){
this.data = data;
}
//获取数据 public Object getData() {
return data;
}
//添加数据 public void setData(Object data) {
this.data = data;
}
//获取下一个节点, public Node getNext() {
return next;
}
//设置下一个节点 public void setNext(Node next) {
this.next = next;
}
}
接着就可以写链表类来实现链表的功能了
包括头结点root 与中间的n个数据节点node(包括尾部节点last),主要有几个功能要实现:添加新节点到末尾,添加新节点到指定位置,获取链表大小,获取指定位置的节点数据,移除指定位置的节点
public class LinkedList {
//链表的长度
private int size = 0;
//链表的头结点,内容为null
private Node root = new Node(null);
//链表的尾部:尾插法
private Node last = root;
//构造方法,初始化链表
public LinkedList() {
}
/**
* add()方法:
* 尾差法:添加新节点到链表的末尾
* @param data:添加的数据
*/
public void add(Object data) {
//创建本node对象的时候初始化数据:data
Node node = new Node(data);
//尾差法:添加到链表的末尾
//设置尾部last的下一个为:node
last.setNext(node);
//更新链表尾部last
last = node;
//size增加
size++;
}
/**
* 获取链表大小
*
* @return :链表长度
*/
public int size() {
return size;
}
/**
* 获取链表第index的数据data
*
* @param index :要获取的第i个链表
* @return :第index的个链表的数据内容
*/
public Object get(int index) {
Node node = root.getNext();
if (index < 0 || index > size) {
return null;
}
for (int i = 0; i < index; i++) {
node = node.getNext();
}
return node.getData();
}
/**
* 移除第index的节点node
*
* @param index :第i个
* @return
*/
public Object remove(int index) {
Node node = root.getNext();
if (index < 0 || index > size) {
return 0;
}
//若要移除的index为第一个node,index为0,不存在index-1,则单独设置
if (index == 0) {
//setNext链接上一个和下一个 :上一个为root,下一个为node.getNext()
root.setNext(node.getNext());
//清除该节点的引用域为null:next
node.setNext(null);
size--;
}
//移除的index不为0
else {
//获取三个节点:上一个node、这个removenode、下一个nextnode
//获取要移除node的上一个node
for (int i = 0; i < index - 1; i++) {
node = node.getNext();
}
// 获取要移除的node
Node removenode = node.getNext();
// 获取要移除的下一个node
Node nextnode = removenode.getNext();
// setNext链接上一个和下一个:上一个为node,下一个为nextnode
node.setNext(nextnode);
//清除该node的引用域为null:next
removenode.setNext(null);
size--;
}
return 0;
}
}
如果对单链表的操作能够掌握的话,剩下的这几种链表,相信也能很快掌握,只不过把node中的基本数据改一下,增删的时候多一两行代码。
对于循环链表,你可以想象成y一个闭环的链表。也就是最后一个元素又指向了第一个元素。双向链表每一个节点既指向前驱又指向后继。
双向链表相对于单链表还是比较复杂的,毕竟每个节点多了一个前驱,因此对于插入和删除要格外小心。双向链表的优点在于对每个节点的相邻接点操作时候,效率会比较高。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。