算法是什麼(二)手寫個鏈表(java)

算法是什麼(二)手寫個鏈表(java)html

 

liuyuhang原創,未經容許禁止轉載java

 

目錄node

算法是什麼(〇)算法

 

不少語言的API中都提供了鏈表實現,或者擴展庫中實現了鏈表。
數組

可是更多的狀況下,Map(或hash)和List(非定容數組)的使用率更高。數據結構

這並不是意味着鏈表不該該掌握或不使用了。ide

 

鏈表本質上是一種及其高等的數據結構展示,擴展性極強。工具

鏈表可輕鬆擴展成樹結構,二叉樹,環,棧,隊列,雙向隊列等。post

 

不少種數據結構都是依據鏈表的形式擴展出來的,雖然我知道的並很少,可是我知道鏈表的重要性。測試

因此,手寫一個鏈表試試。

 

一、本質

 

鏈表的本質是Node(節點),其中保存着信息(info),前一個節點(prevNode),後一個節點(nextNode)。

和基礎操做API構成

 

二、特性

 

鏈表爲了操做的方便性,多數會將鏈表作成雙向鏈表,即既包含next,又包含prev

 

三、基礎API

 

鏈表的操做,至少須要增刪改查,否則還算啥容器了:

  增:默認從末尾添加,添加指定index,在首添加三種方式添加單一元素。

  刪:刪除頭,刪除尾,刪除指定index的元素,刪除當前指針元素。

  改:設置頭,設置尾,設置指定index的元素,設置當前指針元素。

  查:獲取當前指針元素,獲取首元素,獲取尾元素,獲取下一個元素,獲取上一個元素,獲取指定index的元素

 

  有些API還提供了更多的操做:

  獲取當前容器的size

  獲取當前指針的index

  迭代器

  排序工具

  判空

  克隆

  轉數組

  逆轉

  去重複

  序列化

  等等。。。

 

鏈表可作的操做會比想象的多的多。

 

四、Java中的鏈表

 

Java中經常使用的鏈表是LinkedList,實現了List接口,繼承AbstractLinkedList。同時還有其餘接口

 

同時,還有Queue大類,並不是在Collection接口下,可是底層有些是使用鏈表實現的,功能有些是重複的。

對於須要做爲原子操做的各類功能的隊列來講,能夠考慮。

 

在擴展Java中的鏈表的時候,有幾種方式供選擇:

  ①繼承LinkedList,添加擴展算法;

  ②實現List,繼承AbstractLinkedList,同時擴展算法;

  ③使用裝飾模式,在構造器中調用鏈表的構造器,同時擴展算法;

  ④不受約束本身寫一個吧。。。

 

五、寫一個簡單的鏈表

 

我嘗試寫了一個簡單的鏈表,之前也大概看過C的鏈表和Java的鏈表,寫的過程當中全憑記憶,

大約花了十個小時才寫完,哩哩啦啦好多天。

 

代碼拙劣,爲了之後嘗試鏈表的其餘算法(排序,轉換,反轉,環鏈表,擴展二叉樹)作準備。

 

代碼以下:

 

package com.FM.ArrayStudy;

public class SimpleLinkedList<T> {

    private Node<T> pointer;// 當前指針節點
    private Node<T> firstNode;// 首個節點
    private Node<T> lastNode;// 末尾節點
    private Integer index = 0;// 當前指針index
    private Integer size = 0;// 當前容量

    /**
     * 獲取當前pointer的info
     * @return
     */
    public T getThis() {
        if (null == pointer) {
            return firstNode.info;
        } else {
            return pointer.info;
        }
    }

    /**
     * 獲取下一個元素的內容,若沒有下一個元素,則返回null
     * 
     * @return
     */
    public T getNext() {
        if (index.equals(size - 1)) {
            return null;
        } else {
            if (null == pointer) {
                pointer = firstNode;
                pointer = pointer.next;
                T info = pointer.info;
                index++;
                return info;
            } else {
                pointer = pointer.next;
                T info = pointer.info;
                index++;
                return info;
            }
        }
    }

    /**
     * 修改指定index的元素的方法
     * 
     * @param index
     * @param t
     * @throws Exception
     */
    public void set(Integer index, T t) throws Exception {
        if (index > -1 && index < size - 1) {
            Node<T> node = getNodeByIndex(index);
            node.info = t;
        } else {
            throw new Exception("get ele " + index + " out of index");
        }
    }

    /**
     * 修改首元素
     * 
     * @param t
     */
    public void setFirst(T t) {
        firstNode.info = t;
    }

    /**
     * 修改尾元素
     * 
     * @param t
     */
    public void setLast(T t) {
        lastNode.info = t;
    }

    /**
     * 從指定index移除node的方法
     * 
     * @param index
     * @throws Exception
     */
    public void remove(Integer index) throws Exception {
        if (index > -1 && index < size) {
            if (index.equals(0)) {
                Node<T> node = getNodeByIndex(1);
                firstNode = node;
                firstNode.prve = null;
            } else if (index.equals(size - 1)) {
                Node<T> node = getNodeByIndex(size - 2);
                lastNode = node;
                lastNode.next = null;
            } else {
                Node<T> node = getNodeByIndex(index);
                Node<T> nextNode = node.next;
                Node<T> prveNode = node.prve;
                prveNode.next = nextNode;
                nextNode.prve = prveNode;
                node = null;
            }
            size--;
        } else {
            throw new Exception("get ele " + index + " out of index");
        }

    }

    /**
     * 獲取當前元素在鏈表中的位置
     * 
     * @return
     */
    public int getIndex() {
        return index;
    }

    /**
     * 獲取當前鏈表size的方法
     * 
     * @return
     */
    public Integer size() {
        return size;
    }

    /**
     * 判斷容器是否爲空的方法,爲空返回true
     * 
     * @return
     */
    public boolean isEmpty() {
        if (size.equals(0)) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 根據index查詢鏈表中元素的方法
     * 
     * @param index
     * @return
     * @throws Exception
     */
    public T getByIndex(Integer index) throws Exception {
        if (index > -1 && index < size) {
            Node<T> nodeByIndex = getNodeByIndex(index);
            return nodeByIndex.info;
        } else {
            throw new Exception("get ele " + index + " out of index");
        }
    }

    /**
     * 根據index獲取node的方法
     * 
     * @param index
     * @return
     */
    private Node<T> getNodeByIndex(Integer index) {
        Node<T> temp = firstNode;// 取firstnode
        if (index != 0) {// 查看當前index,若index!=0,則遞歸直到index
            for (int i = 0; i < index; i++) {
                temp = temp.next;
            }
        }
        this.index = index;// 調整當前index
        return temp;// 返回節點
    }

    /**
     * 向鏈表末尾默認添加一個元素的方法
     * 
     * @param t
     */
    public void add(T t) {
        if (size == 0) {// 首次建立
            Node<T> node = new Node<T>();
            firstNode = node;
            lastNode = node;
            node.info = t;
            size++;
        } else {
            lastNode.next = new Node<T>();
            lastNode.next.info = t;
            lastNode.next.prve = lastNode;
            lastNode = lastNode.next;
            size++;
        }
    }

    /**
     * 在首添加元素
     * 
     * @param t
     */
    public void addFirst(T t) {
        if (size == 0) {
            add(t);
        } else {
            Node<T> node = new Node<T>();
            node.info = t;
            node.next = firstNode;
            node.prve = null;
            firstNode.next = node;
            size++;
        }
    }

    /**
     * 在尾部添加元素
     * 
     * @param t
     */
    public void addLast(T t) {
        add(t);
    }

    /**
     * Node節點 鏈表內部數據結構和指針
     * 
     * @author Liuyuhang
     * @param <T>
     */
    private class Node<T> {
        T info;// 儲存info
        Node<T> next;// 下一個節點指針
        Node<T> prve;// 上一個節點指針

        @Override
        public String toString() {// 同時打印next和prev會致使無限引用,堆棧溢出
            return "Node [info=" + info + ", next=" + next + "]";
        }

    }

    @Override
    public String toString() {// 打印first節點會由於next引出整個鏈表的全部內容
        return "SimpleLinkedList [node=" + firstNode + "]";
    }

}

 

測試可用,本身拿去玩吧。

 

以上!

相關文章
相關標籤/搜索