链表为数据结构中的一种,分为单链表和双链表。
例如在HashMap的底层数据结构中就采用了单链表来进行存储。LinkedList采用了双向链表来进行存储。
这里主要记录一下单链表的学习和理解。
单链表的存储类似栈,是一种先进后出的原则。在链表中插入时直接插入到表头。这种原则决定了链表的操作效率很高但是遍历并不高。
如果采用尾插法效率会很慢,所以采用插入到表头的方式。
单链表的内容由一个个Node节点组成,每个节点通常包含两部分:data 节点数据,next 下个节点的地址。
任何的操作都通过head节点来开始进行。因为只有每个节点才知道下一个节点的所在。(在内存中每个节点并不是连续的,所在位置由上一个节点所知)。
这是由5个节点组成的链表, 头节点head为A,而除头节点外,所有的节点都由上个节点的next指针指向。
因为是先进后出原则,在添加新的节点时,是从右至左操作的,直接添加在头节点,例如插入F 节点。
Head F -> A -> B -> C -> D -> E ->^ 。这时F的next指针指向A的地址0001 。
简单实现单链表增删改查。
package Chapter1;
/**
* 单链表实现
* <p>
* Created by yu on 2017/9/12.
*/
public class LinkList<T> {
/**
* 内部节点类
*/
class Node<N> {
private Node<N> next;
private N data;
public Node(N data) {
this.data = data;
}
}
/**
* 头结点
**/
private Node head = null;
public LinkList() {
}
/**
* 添加一个节点,采用插入表头原则。
*/
public void addNode(T data) {
Node node = new Node<>(data);
node.next = head;
head = node;
}
/**
* 打印链表
*/
public void print() {
Node node = head;
for (; node != null; node = node.next) {
System.out.print(node.data + " ");
}
System.out.println();
}
/**
* 判断链表是否为空
*/
public Boolean isEmpty() {
if (head == null) {
return true;
}
return false;
}
/**
* 删除一个元素,直接删除头元素。效率很高
*/
public void removeByHead() {
if (!isEmpty()) {
head = head.next;
return;
}
System.out.println("List is null");
}
/**
* 删除链表中遇到的第一个内容相同元素
*/
public void removeByData(T data) {
if (!isEmpty()) {
Node node = head, before = null;
while (node != null) {
if (node.data.equals(data)) {
if (before == null) {
head = head.next;
} else {
before.next = node.next;
}
return;
}
before = node;
node = node.next;
}
}
System.out.println("List is null");
}
/**
* 替换链表中遇到的第一个内容相同元素
*/
public void repalce(T srcData, T proData) {
Node node = head;
while (node != null) {
if (node.data.equals(srcData)) {
node.data = proData;
return;
}
node = node.next;
}
}
/**
* 查询链表中遇到的第一个元素所在位置
* 如果链表为空或者未找到返回-1
*/
public int indexOf(T data) {
if (isEmpty()) {
return -1;
}
int index = 0;
Node node = head;
while (node != null) {
if (node.data.equals(data)) {
return index;
}
node = node.next;
index++;
}
return -1;
}
public static void main(String[] args) {
LinkList<String> linkList = new LinkList<String>();
linkList.addNode("1");
linkList.addNode("3");
linkList.addNode("5");
linkList.addNode("4");
linkList.addNode("5");
linkList.addNode("7");
System.out.print("初始链表为:");
linkList.print();
linkList.repalce("4", "9");
System.out.print("替换后的链表为:");
linkList.print();
System.out.println("链表是否为空:" + linkList.isEmpty());
linkList.removeByData("5");
System.out.print("删除指定元素后的链表为:");
linkList.print();
System.out.println("元素所在的索引位置:" + linkList.indexOf("3"));
}
}