Ex1_3_31 双向链表DulLinkList
import edu.princeton.cs.algs4.StdIn;import edu.princeton.cs.algs4.StdOut;public class DulLinkList<Item> {private class DulNode {Item item;DulNode left;DulNode right;}private DulNode head;private DulNode tail;private int size;public int getSize() {return size;}public boolean isEmpty() {return head == null;}//从表头插入节点public void headInsert(Item item) {DulNode current = head;head = new DulNode();head.item = item;if (isEmpty()) {tail = head;}//链表为空时head,tail指向一个节点else {head.right = current;}size++;}//从表尾插入节点public void tailInsert(Item item) {DulNode current = tail;tail = new DulNode();tail.item = item;tail.left = current;if (isEmpty()) {head = tail;//tail = head错误,两个永远为null}//链表为空时head,tail指向一个节点else {current.right = tail;}size++;}//从表头删除节点public Item headDel() {Item item = head.item;head = head.right;size--;return item;}//从表尾删除节点public Item tailDel() {Item item = tail.item;tail = tail.left;size--;return item;}//在指定节点前插入节点public void beforeInsert(DulNode exist, Item item) {DulNode dulNode = new DulNode();dulNode.item = item;if(exist.left == null) headInsert(item);else{exist.left.right = dulNode;dulNode.left = exist.left;exist.left = dulNode;dulNode.right = exist;size++;}}//在指定节点后插入节点public void afterInsert(DulNode exist, Item item){DulNode dulNode = new DulNode();dulNode.item = item;if(exist.right == null) tailInsert(item);else{exist.right.left = dulNode;dulNode.right = exist.right;exist.right = dulNode;dulNode.left = exist;size++;}}//删除指定节点public Item del(DulNode dulNode){Item item = dulNode.item;if (dulNode == head) headDel();else if(dulNode == tail) tailDel();else{dulNode.left.right = dulNode.right;dulNode.right.left = dulNode.left;}return item;}//测试用例public static void main(String[] args){DulLinkList linkList = new DulLinkList();while(!StdIn.isEmpty()){String s = StdIn.readString();linkList.tailInsert(s);}linkList.beforeInsert(linkList.head,-1);StdOut.println(linkList.size + " elements");StdOut.println(linkList.head.item);StdOut.println(linkList.tail.item);}}
要点:
- 插入节点时,当链表为空,head,tail都指向新节点,注意
//实例化表头DulNode current = head;head = new DulNode();head.item = item;if (isEmpty()) {tail = head;}//链表为空时head,tail指向一个节点else {head.right = current;}//实例化表尾DulNode current = tail;tail = new DulNode();tail.item = item;tail.left = current;if (isEmpty()) {head = tail;//tail = head错误,两个永远为null}//链表为空时head,tail指向一个节点else {current.right = tail;}
将实例化的节点赋值给空引用,才能让tail与head都指向实例化节点,若赋值顺序颠倒,两节点用为null
- 注意在指定节点前/后插入节点,要判断指定节点是否是头/尾结点,否则会产生空指针错误
- 插入节点时连接顺序不同
//前插if(exist.left == null) headInsert(item);else{exist.left.right = dulNode;dulNode.left = exist.left;exist.left = dulNode;dulNode.right = exist;size++;}//后插if(exist.right == null) tailInsert(item);else{exist.right.left = dulNode;dulNode.right = exist.right;exist.right = dulNode;dulNode.left = exist;size++;}
在指定节点前插入节点时:在AB中指定B插入C,则先连接A.right和B.left再连接BC
在指定节点后插入节点时:在AB中指定A插入C,则先连接C.right和B.left再连接AC
