線性鏈表的雙向鏈表——java實現


.線性表鏈式存儲結構:將采用一組地址的任意的存儲單元存放線性表中的數據元素。
鏈表又可分為:

  • 單鏈表:每個節點只保留一個引用,該引用指向當前節點的下一個節點,沒有引用指向頭結點,尾節點的next引用為null。

  • 循環鏈表:一種首尾相連的鏈表。

  • 雙向鏈表:每個節點有兩個引用,一個指向當前節點的上一個節點,另外一個指向當前節點的下一個節點。


下面給出線性表雙向鏈表的實現:java中LinkedList是線性表的鏈式實現,是一個雙向鏈表。

 

import java.util.NoSuchElementException;


//線性表雙向鏈表存儲結構
public class DuLinkList<T> {

    //定義一個內部類Node,Node實例代表鏈表的節點
    private class Node{
        //保存節點的數據
        private T data;
        //指向上一個節點的引用
        private Node prev;
        //指向下一個節點的引用
        private Node next;
        //無參數的構造器
        public Node(){
            
        }
        //初始化全部屬性的構造器
        public Node(T data, Node prev, Node next){
            this.data = data;
            this.prev = prev;
            this.next = next;
        }        
    }
    //保存該鏈表的頭結點
    private Node header;
    //保存該鏈表的尾節點
    private Node tail;
    //保存該鏈表中已包含的節點數
    private int size;
    //創建空鏈表
    public DuLinkList(){
        //空鏈表,header與tail都是null
        header = null;
        tail = null;
    }
    //以指定數據元素來創建鏈表,該鏈表只有一個元素
    public DuLinkList(T element){
        header = new Node(element, null, null);
        tail = header;
        size++;
    }
    //判斷鏈式線性表是否為空鏈表
    public boolean empty(){
        return size == 0;
    }
    //清空線性表
    public void clear(){
        for(Node current = header; current != null;){
            Node next = header.next;
            current.data = null;
            current.prev = null;
            current.next = null;
            current = next;
        }
        header = null;
        tail = null;
        size = 0;
    }
    //獲取鏈式線性表中索引為index處的元素
    public T get(int index){
        return getNodeByIndex(index).data;
    }
    //根據索引index獲取指定位置的節點
    private Node getNodeByIndex(int index){
        if(index < 0 || index > size -1){
            throw new IndexOutOfBoundsException("線性表索引越界");
        }
        if(index < (size >> 1)){
            //從header節點開始遍歷
            Node current = header;
            for(int i=0; i < index; i++){
                current = current.next;
            }
            return current;
        }else{
            Node current = tail;
            for(int i = size - 1; i > index; i--){
                current = current.prev;
            }
            return current;
        }
    }
    //查找鏈式線性表中指定元素的索引
    public int locate(T element){
        Node current = header;
        for(int i=0;i<size && current != null;i++, current = current.next){
            if(current.data.equals(element)){
                return i;
            }
        }
        return -1;
    }
    //返回鏈表的長度
    public int length(){
        return size;
    }
    //向線性鏈表的表頭插入一個元素
    public void addFirst(T element){
        linkFirst(element);
    }
    //在線性鏈表表頭插入一個元素
    public void linkFirst(T element){
        Node f = header;
        Node newNode = new Node(element,null,f);
        header = newNode;
        if(f == null){
            tail = newNode;
        }else{
            f.prev = newNode;
        }
        size++;
    }
    //向線性鏈表的表尾插入一個元素
    public void addTail(T element){
        linkTail(element);
    }
    //在線性鏈表的表尾插入一個元素
    public void linkTail(T element){
        Node t = tail;
        Node newNode = new Node(element, t, null);
        tail = newNode;
        if(t == null){
            header = newNode;
        }else{
            t.next = newNode;
        }
        size++;
    }
    //在線性表中某個元素前面插入一個節點
    public void linkBefore(T element, Node node){
        Node pre = node.prev;
        Node newNode = new Node(element, pre, node);
        node.prev = newNode;
        if(pre == null){
            header = newNode;
        }else{
            pre.next = newNode;
        }
        size++;
    }
    //向線性鏈表中的指定位置插入一個元素
    public void insert(T element, int index){
        if(index < 0 || index > size){
            throw new IndexOutOfBoundsException("線性表索引越界");
        }
        if(index == size){
            addTail(element);
        }else{
            linkBefore(element,getNodeByIndex(index));
        }
    }
    //移走線性鏈表的頭結點
    public void removeFirst(){
        Node first = header;
        if(first == null)
            throw new NoSuchElementException("此節點不存在");
        unlinkFirst(first);
    }
    //刪除頭結點
    public void unlinkFirst(Node node){
        Node next = node.next;    
        node.data = null;
        node.next = null;
        header = next;
        if(next == null){
            tail = null;
        }else{
            next.prev = null;
        }
        size--;
    }
    //移走線性鏈表的尾節點
    public void removeTail(){
        Node last = tail;
        if(last == null)
            throw new NoSuchElementException("此節點不存在");
        unlinkLast(last);
    }
    //刪除尾節點
    public void unlinkLast(Node node){
        Node pre = node.prev;
        node.data = null;
        node.prev = null;
        tail = pre;
        if(pre == null){
            header = null;
        }else{
            pre.next = null;
        }
        size--;
    }
    //移走線性表中的任意一個節點
    public void remove(int index){
        if(index < 0 || index >size - 1){
            throw new IndexOutOfBoundsException("線性表越界");
        }
        unlink(getNodeByIndex(index));
    }
    //刪除線性表中任意一個元素
    public void unlink(Node node){
        Node pre = node.prev;
        Node next = node.next;
        node.data = null;
        if(pre == null){
            header = next;
        }else{
            pre.next = next;
            node.prev = null;
        }
        if(next == null){
            tail = pre;
        }else{
            next.prev = pre;
            node.next = null;
        }
        size--;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM