基础知识
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
单向链表
简介:
- Data 数据 + Next 指针,组成一个单链表的内存结构 ;
- 第一个内存结构称为 链头,最后一个内存结构称为 链尾;
- 链尾的 Next 指针设置为 NULL [指向空];
- 单链表的遍历方向单一【只能从链头一直遍历到链尾】
java实现
跑一遍代码可以帮助理解
package test;
public class SingleLinkedList {
private int size;// 链表节点的个数
private Node headNode;// 头节点
public SingleLinkedList() {
size = 0;
headNode = null;
}
// 链表的每个节点类
private class Node {
private Object data;// 每个节点的数据
private Node next;// 每个节点指向下一个节点的连接
public Node(Object data) {
this.data = data;
}
}
// 在链表头添加元素
public Object addHead(Object obj) {
Node newHead = new Node(obj);
if (size == 0) {
headNode = newHead;
} else {
newHead.next = headNode;
headNode = newHead;
}
size++;
return obj;
}
//在链表尾部添加元素
public boolean addNodeAtEnd(Object obj) {
Node endNode=new Node(obj);
if(size == 0) {
headNode = endNode;
return true;
}
int tempSize = size;
Node current = headNode;
while(tempSize > 0) {
if(current.next == null) {
current.next = endNode;
size++;
return true;
}else {
current = current.next;
tempSize--;
}
}
return false;
}
// 在链表头删除元素
public Object deleteHead() {
Object obj = headNode.data;
headNode = headNode.next;
size--;
return obj;
}
// 查找指定元素,找到了返回节点Node,找不到返回null
public Node find(Object obj) {
Node current = headNode;
int tempSize = size;
while (tempSize > 0) {
if (obj.equals(current.data)) {
return current;
} else {
current = current.next;
}
tempSize--;
}
return null;
}
// 删除指定的元素,删除成功返回true
public boolean delete(Object value) {
if (size == 0) {
return false;
}
Node current = headNode;
Node previous = headNode;
while (current.data != value) {
if (current.next == null) {
return false;
} else {
previous = current;
current = current.next;
}
}
// 如果删除的节点是第一个节点
if (current == headNode) {
headNode = current.next;
size--;
} else {// 删除的节点不是第一个节点
previous.next = current.next;
size--;
}
return true;
}
// 判断链表是否为空
public boolean isEmpty() {
return (size == 0);
}
// 显示节点信息
public void display() {
if (size > 0) {
Node node = headNode;
int tempSize = size;
if (tempSize == 1) {// 当前链表只有一个节点
System.out.println("[" + node.data + "]");
return;
}
while (tempSize > 0) {
if (node.equals(headNode)) {
System.out.print("[" + node.data + "->");
} else if (node.next == null) {
System.out.print(node.data + "]");
} else {
System.out.print(node.data + "->");
}
node = node.next;
tempSize--;
}
System.out.println();
} else {// 如果链表一个节点都没有,直接打印[]
System.out.println("[]");
}
}
}
双向链表
简介
- Data 数据 + Next 指针 + Prev 指针,组成一个双向链表的内存结构;
- 第一个内存结构称为 链头,最后一个内存结构称为 链尾;
- 链头的 Prev 指针设置为 NULL, 链尾的 Next 指针设置为 NULL;
- Prev 指向的内存结构称为 前驱, Next 指向的内存结构称为 后继;
- 双向链表的遍历是双向的,即如果把从链头的 Next 一直到链尾的[NULL] 遍历方向定义为正向,那么从链尾的 Prev 一直到链头 [NULL ]遍历方向就是反向;
java实现
跑一遍代码可以帮助理解
package test;
/**
* 双向链表
*/
public class TwoWayLinkedList {
private Node headNode;//链表头节点
private Node tailNode;//链表尾节点
private int size;//链表长度
private class Node {
private Object data;
private Node pre;
private Node next;
public Node(Object data) {
this.data = data;
}
}
public TwoWayLinkedList() {
this.headNode = null;
this.tailNode = null;
this.size = 0;
}
//在链表头添加节点
public void addHead(Object data){
Node node = new Node(data);
if(size == 0) {
headNode = node;
tailNode = node;
}else {
Node temp = headNode;
headNode = node;
headNode.next = temp;
temp.pre = headNode;
}
size++;
}
//在链表末尾添加节点
public void addTail(Object data) {
Node node = new Node(data);
if(size == 0) {
headNode = node;
tailNode = node;
}else {
Node temp = tailNode;
tailNode = node;
tailNode.pre = temp;
temp.next = tailNode;
}
size ++;
}
//删除链表头
public void deleteHead() {
if(size == 0) {
return;
}else if(size == 1) {
headNode =null;
tailNode = null;
}else {
headNode=headNode.next;
headNode.pre = null;
}
size --;
}
//删除链表尾
public void deleteTail() {
if(size == 0) {
return;
}else if(size == 1) {
headNode =null;
tailNode = null;
}else {
tailNode = tailNode.pre;
tailNode.next = null;
}
size --;
}
//找到指定元素
public void findOneNode(Object data) {
if(size == 0) {
return;
}
Node current = headNode;
int tempSize = size;
while(tempSize >0) {
if(data.equals(current.data)) {
System.out.println("找到指定元素。"+data.toString());
return;
}
current = current.next;
tempSize --;
}
}
//显示节点信息
public void display(){
if(size >0){
Node node = headNode;
int tempSize = size;
if(tempSize == 1){//当前链表只有一个节点
System.out.println("["+node.data+"]");
return;
}
while(tempSize>0){
if(node.equals(headNode)){
System.out.print("["+node.data+"->");
}else if(node.next == null){
System.out.print(node.data+"]");
}else{
System.out.print(node.data+"->");
}
node = node.next;
tempSize--;
}
System.out.println();
}else{//如果链表一个节点都没有,直接打印[]
System.out.println("[]");
}
}
}
循环链表
将单向链表的头尾相接就是单向循环链表,将双向链表的头尾相接就是双向循环链表。
注
- 文章是个人知识点整理总结,如有错误和不足之处欢迎指正。
- 如有疑问、或希望与笔者探讨技术问题(包括但不限于本章内容),欢迎添加笔者微信(o815441)。请备注“探讨技术问题”。欢迎交流、一起进步。
参考文献:
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/69853.html