双向链表
链表是是一种重要的数据结构,有单链表和双向链表之分;本文我将重点阐述不带头结点的双向链表:
不带头结点的带链表
我将对双链表的增加和删除元素操作进行如下解析
1.增加元素(采用尾插法)
(1)链表为空
新建结点,将头结点first和尾节点last都指向新建结点,尾节点的next指向空。
空链表增加元素
(2)链表非空
先定义一个临时的结点temp保存当前的尾节点,将尾节点last指向新建结点,并将last的prev指向temp,temp的next指向last.
非空链表增加元素
2.删除指定下标的元素
我将分以下三种情况进行讨论
(1)要删除元素为头结点
用node保存当前头结点first,并将头结点first指向first.next且将现在的first.prev置为空,将node.的next、data分别置为空。
删除头结点
(2)要删除元素为尾节点
用节点node保存当前的尾节点,将last指向当前尾节点的前一个节点last.prev,并将现last.next置为空,将以前的last即node节点的prev和data置空。
删除尾结点
(3)要删除元素为中间节点
用节点node保存要删除的节点,并将要删除节点的前一个节点的next指向要删除节点的下一个节点;要删除节点的下一个节点的prev指向要删除节点的还是那个一个节点;即node.prev. next = node.next;node.next.prev = node.prev。并将要删除节点的prev、next及data置为null.
删除中间结点
package Struct; interface Link{ void add(Object obj); boolean remove(int index); boolean contain(Object obj); int indexOf(Object obj); boolean set(int index,Object obj); Object get(int index); int length(); void clear(); Object[] toArray(); void printArray(Object[] obj); void printLink(); } class Factory{ private Factory(){} public static Link getLinkInstance(){ return new LinkImpl(); } } class LinkImpl implements Link{ private Node first; private Node last; private int size; private class Node{ private Node prev; private Node next; private Object data; public Node(Object data){ this.data = data; } } public void add(Object obj) { //要插入元素为空 if(obj == null){ return; } Node node = new Node(obj); //空链表 if(first == null){ first = last = node; first.next = null; size++; }else{ //非空链表(尾插) Node temp = this.last; temp.next = node; last = node; last.prev = temp; size++; } } //删除 public boolean remove(int index) { //指定下标不合法 if(index >= size){ return false; } Node node = first; //要删除的节点为头结点 if(index == 0){ first = node.next; first.prev = null; node.prev = node.next = null; node.data = null; size--; return true; } //要删除节点为尾节点 if(index == size-1){ Node node1 = last; last = node1.prev; last.next = null; node1.prev = node1.next = null; node1.data = null; size--; return true; } //要删除节点为中间节点 Node node3 = get(index); node3.prev.next = node3.next; node3.next.prev = node3.prev; node3.prev = node3.next = null; node3.data = null; size--; return true; } //查看元素是否包含在链表中 public boolean contain(Object obj) { //空链表 if(first == null&&first.next==null){ return false; } for(Node node = first;node!=null;node=node.next){ if(node.data==obj){ return true; } } return false; } //求取元素obj的下标 public int indexOf(Object obj) { Node node = first; int signal = 0; //空链表 if(first== null&& first.next == null){ return -1; }else{ for(node = first;node!=null;node=node.next){ if(node.data == obj){ return signal; } signal++; } } return signal; } //修改index处的值为obj public boolean set(int index, Object obj) { //指定位置不存在 if(index<0||index >= size){ return false; } //指定下标超过链表长度 if(index >= size){ return false; } Node node = first; //若链表头结点是要修改的元素 if(node == get(index)){ node.data = obj; } Object getObject = get(index); for(node = first;node !=null;node=node.next){ if( getObject == node){ node.data = obj; } } return true; } //取得index处的元素 public Node get(int index) { if(first==null&&first.next==null){ return null; } //要查找下标不在范围内 if(index >= size){ return null; } Node node = first; //要查找元素在中间元素的左侧 if(index >=0 && index <= (index<<1)){ for(int i = 0;i <= index - 1;i++){ if(i == index){ return node; } node =node.next; } } else if(index > (index<<1)){ //要查找元素在中间元素的右侧 for(int i = index; i < size-1;i++){ if(i == index){ return node; } node = node.next; } } return node; } //求链表长度 public int length() { //空链表 if(first == null){ return 0; } return this.size; } //清空链表 public void clear() { Node node = first; if(first == null && first.next == null){ return; } for(node = first.next;node!=null;){ Node temp = node; node.prev = node.next = null; node.data = null; node = node.next; size--; } first.next = null; first.data = null; size--; } //将链表转换成Object数组 public Object[] toArray() { //空链表 if(first == null && first.next == null){ return null; }else{ Object[] linkObject = new Object[this.size];//向上转型 Node node = first; for(int i = 0;i<size;i++){ linkObject[i] = node.data; node = node.next; } return linkObject; } } //打印Object数组 public void printArray(Object[] obj){ for(int i = 0;i < obj.length;i++){ System.out.print(obj[i]+" <-> "); } } //打印链表 public void printLink() { Node node = first; for(node = first;node!=null;node=node.next){ System.out.print(node.data+" <——> "); } System.out.println(); } } public class DoubleLinkList { public static void main(String[] args) { Link link = Factory.getLinkInstance(); System.out.println("\n"+"=================以下为add测试函数==================="); link.add("我是开始位置"); link.add("第一名"); link.add("第二名"); link.add("第三名"); link.add("我是结束位置"); System.out.println("\n"+"===============以下为printLink测试函数==============="); link.printLink(); System.out.println("\n"+"===============以下为indexOf测试函数================"); System.out.println(link.indexOf("第二名")); System.out.println(link.indexOf("我是结束位置")); System.out.println("\n"+"===============以下为contain测试函数================"); System.out.println(link.contain("我是结束位置")); System.out.println(link.contain("hahh")); System.out.println("\n"+"===============以下为get测试函数================"); System.out.println(link.get(0)); System.out.println(link.get(4)); System.out.println(link.get(2)); System.out.println(link.get(8)); System.out.println("\n"+"===============以下为length测试函数================"); System.out.println(link.length()); System.out.println("\n"+"===============以下为set测试函数==================="); System.out.println(link.set(0, "我是特等奖")); link.printLink(); System.out.println("\n"+"===============以下为toArray测试函数==================="); Object[] linkObj = link.toArray(); System.out.println("\n"+"===============以下为printArray测试函数==================="); link.printArray(linkObj); System.out.println("\n"+"===============以下为remove测试函数==================="); //删除尾节点 System.out.println(link.remove(4)); link.printLink(); //删除头结点 System.out.println(link.remove(0)); link.printLink(); //删除中间节点 System.out.println(link.remove(1)); link.printLink(); System.out.println(link.length()); System.out.println("\n"+"===============以下为clear测试函数==================="); link.clear(); System.out.println(link.length()); } }测试结果: