Java造輪子-數(shù)據(jù)結(jié)構(gòu)-線性表

數(shù)據(jù)結(jié)構(gòu)-線性表

@(數(shù)據(jù)結(jié)構(gòu))

線性表是數(shù)據(jù)結(jié)構(gòu)中的邏輯結(jié)構(gòu)??梢源鎯υ跀?shù)組上,也可以存儲在鏈表上。

順序表(數(shù)組)

簡述

用數(shù)組來存儲的線性表就是順序表。

優(yōu)點(diǎn)

  • 查找速度快,因為本身是數(shù)組的查找

缺點(diǎn)

  • 插入和刪除都會伴隨著大量的元素操作和移動

Java代碼造輪子

  • 基本方法架構(gòu)如圖:
  • 這里我們實現(xiàn)的是大小固定的,當(dāng)然我們也可以去詳細(xì)寫一個大小根據(jù)插入而拓展的就像我們常使用的ArrayList一樣。
線性表 順序表(數(shù)組)
 * 
 * MyList(int size) 構(gòu)造函數(shù)指定大小 
 * void destory() 銷毀順序表對象 
 * void clear() 清空順序表內(nèi)元素
 * boolean isEmpty() 判空 
 * boolean isFull() 判滿 
 * int getLength() 獲取當(dāng)前順序表長度 
 * T get(intposition) 根據(jù)位置獲取順序表內(nèi)元素對象 
 * int getPosition(T t) 根據(jù) 元素對象獲取順序表位置 
 * T prior(T t)獲取對象前驅(qū) 
 * T next(T t) 獲取對象后繼
 * 
 * boolean insert(T t) / insert(int position, T t) 
 * 向順序表插入對象,不傳位置就默認(rèn)在最后插入,這里!不是!內(nèi)部調(diào)用insert(int position, T t)
 * 
 * boolean delete(T t) / delete(int position) 
 * 根據(jù)對象或者位置刪除順序表 內(nèi)元素
 * 
 * void traverse(int position) 
 * 遍歷順序表 
 * 
 * abstract void onTraverse()
 * 遍歷順序表得到對象的具體操作
 * @author Rayhahah
 *
 * @param <T> 當(dāng)前順序表中的元素對象類型
  • 代碼實現(xiàn)部分
public abstract class MyList<T> {
    private int mCapacity;
    private Object[] mList;
    private int mLength;

    /**
     * 構(gòu)造函數(shù)
     * 
     * @param size
     *            指定順序表容量
     */
    public MyList(int size) {
        mCapacity = size;
        mList = new Object[mCapacity];
    }

    /**
     * 摧毀當(dāng)前順序表
     */
    public void destory() {
        clear();
        mCapacity = 0;
        mList = null;
        System.gc();
    }

    /**
     * 清空順序表 只需要將長度置為0就可以了
     *  因為獲取表中內(nèi)容的時候,都需要和length做判斷
     */
    public void clear() {
        mLength = 0;
    }

    /**
     * 判斷當(dāng)前順序表是否為空
     * 
     * @return 空:true, 非空:false
     */
    public boolean isEmpty() {
        return mLength == 0;
    }

    /**
     * 判斷當(dāng)前順序表是否為滿
     * 
     * @return 滿:true, 未滿:false
     */
    public boolean isFull() {
        return mLength == mCapacity;
    }

    /**
     * 獲取當(dāng)前 順序表的長度 注意不是容量
     * 
     * @return
     */
    public int getLength() {
        return mLength;
    }

    /**
     * 根據(jù)坐標(biāo)獲取順序表的元素
     * 
     * @param position
     *            坐標(biāo)
     * @return 順序表元素
     */
    public T get(int position) {
        // 不滿足都返回null
        if (position < 0 || position >= mLength || mList == null) {
            return null;
        }

        return (T) mList[position];
    }

    /**
     * 根據(jù)傳入元素返回元素在順序表中的坐標(biāo) 
     * 判斷依據(jù)是 元素的地址
     * 
     * @param t
     * @return 元素所在坐標(biāo)
     */
    public int getPosition(T t) {
        if (isEmpty()) {
            return -1;
        }

        for (int i = 0; i < mLength; i++) {
            if (t == mList[i]) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 獲取傳入元素的前驅(qū) 判斷依據(jù)元素的地址
     * 
     * @param t
     * @return
     */
    public T prior(T t) {
        if (isEmpty()) {
            return null;
        }
        for (int i = 1; i < mLength; i++) {
            if (t == mList[i]) {
                return (T) mList[i - 1];
            }
        }
        return null;
    }

    /**
     * 獲取傳入元素的后繼 判斷依據(jù) 元素的地址
     * 
     * @param t
     * @return
     */
    public T next(T t) {
        if (isEmpty()) {
            return null;
        }
        for (int i = 0; i < mLength; i++) {
            if (t == mList[i]) {
                return (T) mList[i + 1];
            }
        }
        return null;
    }

    /**
     * 插入元素,不指定位置默認(rèn)插入在順序表的最后 
     * 如果順序表已經(jīng)滿了,就返回false 插入成功返回true
     * 
     * @param t
     * @return
     */
    public boolean insert(T t) {
        if (isFull()) {
            return false;
        }
        mList[mLength] = t;
        mLength++;
        return true;
    }

    /**
     * 向指定位置插入元素,其他元素向后退一位
     * 
     * @param position
     * @param t
     * @return
     */
    public boolean insert(int position, T t) {
        T tar = t;
        T temp = null;
        // 滿了以后長度不再變化
        if (!isFull()) {
            mLength++;
        }
        for (int i = position; i < mLength; i++) {
            if (temp != null) {
                tar = temp;
            }
            temp = (T) mList[i];
            mList[i] = tar;
        }
        return true;
    }

    /**
     * 刪除順序表中的指定元素
     * 
     * @param t
     * @return
     */
    public boolean delete(T t) {
        if (isEmpty()) {
            return false;
        }
        T temp = null;
        boolean flag = false;
        for (int i = 0; i < mLength; i++) {
            //找到刪除元素以后就開始將后面元素前移
            if (t == mList[i]) {
                mLength--;
                if (i == mLength) {
                    return true;
                }
                flag = true;
            }
            if (i != mLength) {
                temp = (T) mList[i + 1];
            }
            if (flag) {
                mList[i] = temp;
                if (i == mLength) {
                    return true;
                }

            }
        }
        return false;
    }

    /**
     * 刪除順序表中的指定位置的元素
     * 
     * @param position
     * @return
     */
    public boolean delete(int position) {
        if (isEmpty() || position >= mLength || position < 0) {
            return false;
        }
        for (int i = position; i < mLength; i++) {
            System.out.println(i);
            if (i + 1 >= mLength) {
                mLength--;
                return true;
            }
            mList[i] = mList[i + 1];
            System.out.println(mList[i]);
        }
        return true;
    }

    /**
     * 默認(rèn)遍歷為遍歷整個順序表
     */
    public void traverse() {
        traverse(0);
    }

    /**
     * 指定開始遍歷的位置
     * 
     * @param position
     */
    public void traverse(int position) {
        for (int i = position; i < mLength; i++) {
            onTraverse((T) mList[i]);
        }
    }

    /**
     * 遍歷得到元素所需要的具體操作
     *  交回給用戶自己確定
     * 
     * @param t
     */
    public abstract void onTraverse(T t);

}

鏈表

單鏈表

  • 單向性:鏈表中的節(jié)點(diǎn)只會指向另一個節(jié)點(diǎn),最后的節(jié)點(diǎn)指向null
單鏈表.png

循環(huán)鏈表

  • 形成回路:與單鏈表最大的區(qū)別就是尾節(jié)點(diǎn)指向頭結(jié)點(diǎn)
循環(huán)鏈表.png

雙向鏈表

  • 每個節(jié)點(diǎn)都會指向它的"前節(jié)點(diǎn)"和"后節(jié)點(diǎn)"
  • 頭結(jié)點(diǎn)的"前節(jié)點(diǎn)"指向為null,尾節(jié)點(diǎn)的"后節(jié)點(diǎn)"指向為null
雙向鏈表.png

靜態(tài)鏈表

  • 對于沒有指針的語言,就要使用靜態(tài)鏈表
  • 使用數(shù)組,每個節(jié)點(diǎn)的指向就是保存它指向節(jié)點(diǎn)的數(shù)組中的坐標(biāo)
靜態(tài)鏈表.png

代碼造輪子

  • 在這里我只做了單鏈表的代碼實現(xiàn),其他的鏈表其實也是觸類旁通
  • 這里的功能我只做了基本的方法,想要深入研究的朋友可以參考一下Java源碼的LinkedList相信一定可以有所收獲
  • 基本結(jié)構(gòu):
 * MyLinkedList() 構(gòu)造函數(shù)
 * void clearList() 清空鏈表數(shù)據(jù)
 * 
 * boolean isEmpty() 鏈表判空
 * int getLength() 鏈表的當(dāng)前長度
 * 
 * T get(int position) 根據(jù)坐標(biāo)獲取鏈表中的元素
 * int getPosition(T t) 根據(jù)數(shù)據(jù)對象獲取在鏈表中的位置坐標(biāo)
 * 
 * boolean insert(T t) / insert(int position,T t) 
 * 向鏈表末尾插入數(shù)據(jù)對象 / 向指定位置插入數(shù)據(jù)對象
 * 
 * boolean delete(T t) / delete (int position) 
 * 刪除在鏈表中的傳入數(shù)據(jù)對象 / 刪除指定位置的節(jié)點(diǎn)
 * 
 * void traverse(int position) 
 * 啟動遍歷鏈表
 * abstract void onTraverse() 
 * 遍歷順序表得到對象的具體操作
 * 
 * @author Rayhahah
 *
 * @param <T>
 *            鏈表儲存的數(shù)據(jù)對象類型
  • 具體代碼實現(xiàn):
public abstract class MyLinkedList<T> {
    private MyNode<T> first;
    private int mLength;

    public MyLinkedList() {
        first = new MyNode<T>(null, null);
        mLength = 0;
    }

    /**
     * 判空
     * 
     * @return
     */
    public boolean isEmpty() {
        return mLength == 0;
    }

    /**
     * 清空鏈表
     */
    public void clear() {
        for (MyNode<T> temp = first; temp != null;) {
            MyNode<T> next = temp.next;
            temp.next = null;
            temp.t = null;
            temp = next;
        }
        mLength = 0;
    }

    /**
     * 節(jié)點(diǎn)是否為空
     * 
     * @param myNode
     * @return
     */
    private boolean isNodeNull(MyNode<T> myNode) {
        if (myNode.next == null && myNode.t == null) {
            return true;
        }
        return false;
    }

    /**
     * 向鏈表最后插入節(jié)點(diǎn)
     * 
     * @param t
     * @return
     */
    public boolean insert(T t) {
        return insert(mLength, t);
    }

    /**
     * 向指定位置插入及節(jié)點(diǎn)
     * 
     * @param position
     * @param t
     * @return
     */
    public boolean insert(int position, T t) {
        if (position < 0 || position > mLength) {
            return false;
        }
        mLength++;
        MyNode<T> currentNode = first;
        MyNode<T> currentNodeBefore = null;
        //插入位置是頭節(jié)點(diǎn)的情況
        if (position == 0) {
            MyNode<T> newNode = new MyNode<T>(t, first);
            first = newNode;
            return true;
        }
        for (int i = 0; i < position; i++) {
            currentNodeBefore = currentNode;
            currentNode = currentNode.next;
        }
        //指向后節(jié)點(diǎn)
        MyNode<T> newNode = new MyNode<>(t, currentNode);
        //前節(jié)點(diǎn)指向新節(jié)點(diǎn)就等于插入
        currentNodeBefore.next = newNode;
        return true;
    }

    /**
     * 根據(jù)坐標(biāo)刪除節(jié)點(diǎn)
     * 
     * @param position
     * @return
     */
    public boolean delete(int position) {
        if (position < 0 || position >= mLength) {
            return false;
        }
        mLength--;
        if (position == 0) {
            return deleteFirst(first.next);
        }
        MyNode<T> currentNode = first;
        MyNode<T> currentNodeBefore = null;
        for (int i = 0; i < position; i++) {
            currentNodeBefore = currentNode;
            currentNode = currentNode.next;
        }
        //將要刪除的節(jié)點(diǎn)的前節(jié)點(diǎn)指向  要刪除的節(jié)點(diǎn)的后節(jié)點(diǎn)
        //失去了聯(lián)系節(jié)點(diǎn)就等于被刪除了
        currentNodeBefore.next = currentNode.next;
        return true;
    }

    /**
     * 清楚頭節(jié)點(diǎn)數(shù)據(jù)
     * 
     * @param node
     * @return
     */
    private boolean deleteFirst(MyNode<T> node) {
        first = node;
        return true;
    }

    /**
     * 刪除包含有該數(shù)據(jù)對象的節(jié)點(diǎn)數(shù)據(jù)
     * 
     * @param t
     * @return
     */
    public boolean delete(T t) {
        if (isEmpty()) {
            return false;
        }

        mLength--;
        // 現(xiàn)在節(jié)點(diǎn)
        MyNode<T> currentNode = first;
        // 前節(jié)點(diǎn)
        MyNode<T> currentNodeBefore = null;
        while (currentNode.t != null) {
            if (currentNode.t == t) {
                // 頭節(jié)點(diǎn)
                if (currentNodeBefore == null) {
                    first = currentNode.next;
                } else {
                    currentNodeBefore.next = currentNode.next;
                }
                return false;
            }
            currentNodeBefore = currentNode;
            currentNode = currentNode.next;
        }
        return false;
    }

    /**
     * 根據(jù)坐標(biāo)返回數(shù)據(jù)對象
     * 
     * @param position
     *            坐標(biāo)
     * @return 數(shù)據(jù)對象
     */
    public T get(int position) {
        if (position < 0 || position >= mLength) {
            return null;
        }
        MyNode<T> currentNode = first;
        // 移動至position就可以找到需要的數(shù)據(jù)對象了
        for (int i = 0; i < position; i++) {
            currentNode = currentNode.next;
        }
        return currentNode.t;
    }

    /**
     * 根據(jù)傳入元素獲取在鏈表中的坐標(biāo)
     * 
     * @param t
     *            需要查找坐標(biāo)的對象
     * @return 坐標(biāo)
     */
    public int getPosition(T t) {
        if (isEmpty()) {
            return -1;
        }
        int count = 0;// 獲取當(dāng)前查找到的坐標(biāo)
        MyNode<T> currentNode = first;
        while (currentNode != null) {
            // 找到元素就返回
            if (currentNode.t == t) {
                return count;
            }
            count++;
            currentNode = currentNode.next;
        }
        return -1;
    }

    /**
     * 遍歷整個鏈表
     */
    public void traverse() {
        MyNode<T> currentNode = first;
        while (currentNode.t != null) {
            onTraverse(currentNode.t);
            currentNode = currentNode.next;
        }
    }

    /**
     * 遍歷時對每個元素具體的操作
     * 
     * @param t
     */
    public abstract void onTraverse(T t);

}

最后

線性表是平常我們會用到非常多的一個數(shù)據(jù)結(jié)構(gòu),雖然自己造輪子并沒有什么卵用
不過對于我們思維聯(lián)想的提升,我相信還是有點(diǎn)幫助的
附上 數(shù)據(jù)結(jié)構(gòu)項目的GitHub:
https://github.com/Rayhahah/DataStructure

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文內(nèi)容取自于小甲魚的數(shù)據(jù)結(jié)構(gòu)與算法。http://www.itdecent.cn/p/230e6fde9c75 ...
    阿阿阿阿毛閱讀 3,104評論 0 7
  • 從數(shù)據(jù)的邏輯結(jié)構(gòu)來分,數(shù)據(jù)元素之間存在的關(guān)聯(lián)關(guān)系被稱為數(shù)據(jù)的邏輯結(jié)構(gòu)。歸納起來,應(yīng)用程序中的數(shù)據(jù)大致喲如下四種基本...
    Jack921閱讀 1,174評論 0 2
  • 基礎(chǔ)概念 數(shù)據(jù)結(jié)構(gòu)的分類 在數(shù)據(jù)結(jié)構(gòu)中,按照不同的角度,數(shù)據(jù)結(jié)構(gòu)分為邏輯結(jié)構(gòu)和物理結(jié)構(gòu)(存儲結(jié)構(gòu))。 邏輯結(jié)構(gòu):指...
    IAM四十二閱讀 1,253評論 2 5
  • 1.線性表的定義 線性表:零個或多個數(shù)據(jù)元素的有限序列序列:也就是說元素之間是有順序的,若元素存在多個,則第一個元...
    e40c669177be閱讀 2,210評論 6 15
  • 在上一篇文章中我們簡單說了數(shù)據(jù)結(jié)構(gòu)的概念和數(shù)據(jù)結(jié)構(gòu)與算法的一些關(guān)系,這一篇文章的內(nèi)容是關(guān)于線性表的東西,主要有線性...
    硅谷小蝦米閱讀 1,383評論 1 3

友情鏈接更多精彩內(nèi)容