链表(linked_list)
链表内还有一种特殊的节点称为哨兵 (Sentinel) 节点,也叫做哑元 ( Dummy) 节点,
它不存储数据,通常用作头尾,用来简化边界判断
哨兵其实就是初始化的一个节点,保证链表中永远都不为空,哨兵不参与增删改查,
- 单向链表
/**
* 单向链表
*/
public class SinglyLinkedList implements Iterable<Integer> {
private Node head = null; //头部
//哨兵--头部节点
//不参与遍历增删改等
private Node head1 = new Node(1,null);
/**
* 节点类
*/
private static class Node {
int value;//值
Node next;//下一个节点的指针
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
}
/**
* 增加至头部
*
* @param value
*/
public void addFirst(int value) {
head = new Node(value, head);
}
/**
* 增加至尾部
* 需要循环遍历才能找到尾部
*/
public void addLast(int value) {
Node p = head;
while (p != null && p.next != null) {
p = p.next;
}
//如果链表中没有数据,调用增加至头部的方法
if (p == null) {
addFirst(value);
} else {
p.next = new Node(value, null);
}
}
/**
* 根据下标寻找节点值
*/
public int getByIndex(int index) {
Node p = head;
int i = 0;
while (p != null) {
if (i == index) {
return p.value;
}
i++;
p = p.next;
}
if (p == null) {
throw new ArrayIndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
}
return 0;
}
/**
* 插入指定索引位置
*/
public void insertIndex(int index,int value){
if(index == 0){
addFirst(value);
return;
}
//寻找插入节点之前的那个节点
Node p = head;
int i = 0;
while (p != null){
if(i == (index-1)){
p.next = new Node(value,p.next);
return;
}
i++;
p = p.next;
}
if (p == null) {
throw new ArrayIndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
}
}
/**
* 删除第一个节点
*/
public void removeFirst(){
if(head == null){
return;
}
head = head.next;
}
/**
* 删除指定位置节点
*/
public void remove(int index){
if(index == 0){
removeFirst();
}else{
Node p = head;
int i = 0;
while (p != null){
if(i == (index-1)){
System.out.println(i);
if(p.next == null){
return;
}
p.next = p.next.next;
return;
}
i++;
p = p.next;
}
}
}
/**
* 遍历1
* while循环
*/
public void loop1(Consumer<Integer> consumer) {
Node p = head;
while (p != null) {
consumer.accept(p.value);
p = p.next;
}
}
/**
* 遍历2
* for循环
*/
public void loop2(Consumer<Integer> consumer) {
for (Node p = head; p != null; p = p.next) {
consumer.accept(p.value);
}
}
/**
* 遍历3
* 迭代器循环
*/
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
Node p = head;
@Override
public boolean hasNext() {
return p != null;
}
@Override
public Integer next() {
int v = p.value;
p = p.next;
return v;
}
};
}
/**
* 遍历4
* 递归算法遍历
*/
public void loop3(Node curr) {
System.out.println(curr.value);
if(curr == null){
return;
}
loop3(curr.next);
}
}
- 双向链表
private static class Node{
Node prev;//头节点
int value;
Node next;//尾节点
public Node(Node prev,int value,Node next){
this.prev = prev;
this.value = value;
this.next = next;
}
}
head = new Node(null,1,null);
tail = new Node(null,2,null);
head.next = tail;
tail.prev = head;
- 循环链表
哨兵链表的头尾都指向自己,将来有元素的时候,尾部元素的尾指向哨兵
private static class NodeRound{
NodeRound prev;//头节点
int value;
NodeRound next;//尾节点
public NodeRound(NodeRound prev,int value,NodeRound next){
this.prev = prev;
this.value = value;
this.next = next;
}
}
NodeRound nodeRound = new NodeRound(null,1,null);//哨兵
nodeRound.prev = nodeRound;
nodeRound.next = nodeRound;