双向链表
链表是是一种重要的数据结构,有单链表和双向链表之分;本文我将重点阐述不带头结点的双向链表:
不带头结点的带链表
我将对双链表的增加和删除元素操作进行如下解析
增加元素(采用尾插法)
(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());
}
}
测试结果: