Java 八大数据结构之链表
一:定义
数据结构:是计算机存储、组织数据的形式,指相互之间存在一种或多种特定关系的数据元素的汇合。
二:链表(Linked List)
链表通常由一连串节点组成,每个节点蕴含任意的实例数据(data fields)和一或两个用来指向上一个 / 或下一个节点的地位的链接(”links”)
链表(Linked list)是一种常见的根底数据结构,是一种线性表,然而并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针 (Pointer)。
1. 单向链表(Single-Linked List)
单链表是链表中构造最简略的,一个单链表的节点(Node)分为两局部,第一局部(data)保留或者显示对于节点的信息 ,另一部分 存储下一个节点的地址 。最初一个节点 存储地址的局部指向空值
单向链表只可向一个方向遍历,个别查找一个节点的时候须要从第一个节点开始每次拜访下一个节点,始终拜访到须要的地位。
单向链表的增删改查的实现
public class SingleLinkedList {
private int size;// 链表节点的个数
private Node head;// 头节点
public SingleLinkedList() {
size = 0;
head = null;
}
// 定义一个节点外部类,蕴含数据 Object, 和 Node 节点指针
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) {head = newHead;} else {
newHead.next = head;
head = newHead;
}
size++;
return obj;
}
// 在链表头删除元素
public Object deleteHead() {
Object obj = head.data;
head = head.next;
size--;
return obj;
}
// 查找指定元素,找到了返回 null
public Node find(Object obj) {
Node current = head;
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 = head;
Node previous = head;
while (current.data != value) {if (current.next == null) {return false;} else {
previous = current;
current = current.next;
}
}
// 如果删除的节点是第一个节点
if (current == head) {
head = 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 = head;
int tempSize = size;
if (tempSize == 1) {// 以后链表只有一个节点
System.out.println("[" + node.data + "]");
return;
}
while (tempSize > 0) {if (node.equals(head)) {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("[]");
}
}
}
调用
SingleLinkedList singleLinkedList=new SingleLinkedList();
singleLinkedList.addHead("Rocky");
singleLinkedList.addHead("Tom");
singleLinkedList.addHead("Jacky");
singleLinkedList.addHead("Mark");
// 打印以后链表信息
singleLinkedList.display();
// 删除 Tom
singleLinkedList.delete("Tom");
singleLinkedList.display();
// 查找 Rocky
System.out.println(singleLinkedList.find("Rocky"));
// 后果
System.out: [Mark->Jacky->Tom->Rocky]
System.out: [Mark->Jacky->Rocky]
System.out: com.ruan.mygitignore.SingleLinkedList$Node@c115983
2. 双端链表(它也是单向的只是减少了一个尾结点,这个能够向尾部增加数据,和双向链表区别)
对于单项链表,咱们如果想在尾部增加一个节点,那么必须从头部始终遍历到尾部,找到尾节点,而后在尾节点前面插入一个节点。这样操作很麻烦,如果咱们在设计链表的时候多个对尾节点的援用,那么会简略很多。
public class DoublePointLinkedList {
private Node head;// 头节点
private Node tail;// 尾节点
private int size;// 节点的个数
private class Node{
private Object data;
private Node next;
public Node(Object data){this.data = data;}
}
public DoublePointLinkedList(){
size = 0;
head = null;
tail = null;
}
// 链表头新增节点
public void addHead(Object data){Node node = new Node(data);
if(size == 0){// 如果链表为空,那么头节点和尾节点都是该新增节点
head = node;
tail = node;
size++;
}else{
node.next = head;
head = node;
size++;
}
}
// 链表尾新增节点
public void addTail(Object data){Node node = new Node(data);
if(size == 0){// 如果链表为空,那么头节点和尾节点都是该新增节点
head = node;
tail = node;
size++;
}else{
tail.next = node;
tail = node;
size++;
}
}
// 删除头部节点,胜利返回 true,失败返回 false
public boolean deleteHead(){if(size == 0){// 以后链表节点数为 0
return false;
}
if(head.next == null){// 以后链表节点数为 1
head = null;
tail = null;
}else{head = head.next;}
size--;
return true;
}
// 判断是否为空
public boolean isEmpty(){return (size ==0);
}
// 取得链表的节点个数
public int getSize(){return size;}
// 显示节点信息
public void display(){if(size >0){
Node node = head;
int tempSize = size;
if(tempSize == 1){// 以后链表只有一个节点
System.out.println("["+node.data+"]");
return;
}
while(tempSize>0){if(node.equals(head)){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("[]");
}
}
}
3. 双向链表
咱们晓得单向链表只能从一个方向遍历,那么双向链表它能够从两个方向遍历。
双向链表实现
public class TwoWayLinkedList {
private Node head;// 示意链表头
private Node tail;// 示意链表尾
private int size;// 示意链表的节点个数
// 外部类构建了数据,前驱指针 prev, 向前寻找,后驱指针 next 向后查找
private class Node {
private Object data;
private Node next;// 链接后一个节点
private Node prev;// 链接前一个节点
public Node(Object data) {this.data = data;}
}
public TwoWayLinkedList() {
size = 0;
head = null;
tail = null;
}
// 在链表头减少节点
public void addHead(Object value) {Node newNode = new Node(value);
if (size == 0) {
head = newNode;
tail = newNode;
size++;
} else {
head.prev = newNode;// 原节点的前驱指针链接新节点
newNode.next = head;// 新节点的后驱指针链接原节点
head = newNode;
size++;
}
}
// 在链表尾减少节点
public void addTail(Object value) {Node newNode = new Node(value);
if (size == 0) {
head = newNode;
tail = newNode;
size++;
} else {
newNode.prev = tail;
tail.next = newNode;
tail = newNode;
size++;
}
}
// 删除链表头
public Node deleteHead() {
Node temp = head;
if (size != 0) {
head = head.next;
head.prev = null;
size--;
}
return temp;
}
// 删除链表尾
public Node deleteTail() {
Node temp = tail;
if (size != 0) {
tail = tail.prev;
tail.next = null;
size--;
}
return temp;
}
// 取得链表的节点个数
public int getSize() {return size;}
// 判断链表是否为空
public boolean isEmpty() {return (size == 0);
}
// 显示节点信息
public void display() {if (size > 0) {
Node node = head;
int tempSize = size;
if (tempSize == 1) {// 以后链表只有一个节点
System.out.println("[" + node.data + "]");
return;
}
while (tempSize > 0) {if (node.equals(head)) {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("[]");
}
}
}
调用
TwoWayLinkedList twoWayLinkedList=new TwoWayLinkedList();
twoWayLinkedList.addHead("Rocky");
twoWayLinkedList.addHead("Mark");
twoWayLinkedList.addTail("Jack");
twoWayLinkedList.addTail("Sam");
twoWayLinkedList.display();
END: 强大和无知,不是生存的阻碍,高傲才是。