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

一,列表

實際上,除了通過秩,我們還可以通過其它途徑來確定元素在序列中的位置。我們希望能夠為序列擴充若干新的方法,使之能夠直接以某些節(jié)點做為參數(shù),找到所需的節(jié)點并對其實施操作。

在統(tǒng)一的列表ADT下可以有多種實現(xiàn)形式,而且元素的存儲形式也不盡相同,就這個意義而言,位置(Position)的概念就是對元素的不同形式的抽象和統(tǒng)一,也是對列表元素之間相對“位置”的形式化刻畫。正是在這種抽象的基礎(chǔ)上,我們才可以安全地為列表擴充一整套基于節(jié)點的操作。

按照這一思路,依然可以將列表看作是存放元素的容器,其中的元素各有自己的存放位置,我們只是將它們的位置組織為一個線性的結(jié)構(gòu)。

由秩到位置


二,列表ADT(AbstractDataType)

在引入位置概念對列表“節(jié)點”進行封裝之后,就可以得到一個新的序列ADT,稱作列表(List)。該ADT 支持對列表S 的以下方法:

操作方法 功能描述
first() 若S 非空,則給出其中第一個元素的位置 ;否則,報錯
輸入:無
輸出:位置
last() 若S 非空,則給出其中最后一個元素的位置 ;否則,報錯
輸入:無
輸出:位置
getPrev(p) 若p 不是第一個位置,則給出S 中p 的前驅(qū)所在的位置 ;否則,報錯
輸入:位置
輸出:位置
getNext(p) 若p 不是最后一個位置,則給出S 中p 的前驅(qū)所在的位置 ;否則,報錯
輸入:位置
輸出:位置
replace(p, e) 將處于位置p 處的元素替換為e,并返回被替換的元素
輸入:一個位置和一個對象
輸出:對象
insertFirst(e) 將元素e 作為第一個元素插入S 中,并返回e 的位置
輸入:一個對象
輸出:位置
insertLast(e) 將元素e 作為最后一個元素插入S 中,并返回e 的位置
輸入:一個對象
輸出:位置
insertBefore(p, e) 將元素e 插入于S 中位置p 之前,并返回e 的位置
輸入:一個位置和一個對象
輸出:位置
insertAfter(p, e) 將元素e 插入于S 中位置p 之后,并返回e 的位置
輸入:一個位置和一個對象
輸出:位置
remove(p) 刪除S 中位置p 處的元素
輸入:一個位置
輸出:對象

三,基于雙向鏈表實現(xiàn)的列表

舉一個實現(xiàn)插入的例子

接口

package dsa.List;

import dsa.Vector.ExceptionBoundaryViolation;
import other.Position;

/*
 * 列表ADT接口
 */
public interface List {
    // 查詢列表當前的規(guī)模
    public int getSize();

    // 判斷列表是否為空
    public boolean isEmpty();

    // 返回第一個元素(的位置)
    public Position first();

    // 返回最后一個元素(的位置)
    public Position last();

    // 返回緊接給定位置之后的元素(的位置)
    public Position getNext(Position p) throws ExceptionPositionInvalid,
            ExceptionBoundaryViolation;

    // 返回緊靠給定位置之前的元素(的位置)
    public Position getPrev(Position p) throws ExceptionPositionInvalid,
            ExceptionBoundaryViolation;

    // 將e作為第一個元素插入列表
    public Position insertFirst(Object e);

    // 將e作為最后一個元素插入列表
    public Position insertLast(Object e);

    // 將e插入至緊接給定位置之后的位置
    public Position insertAfter(Position p, Object e)
            throws ExceptionPositionInvalid;

    // 將e插入至緊靠給定位置之前的位置
    public Position insertBefore(Position p, Object e)
            throws ExceptionPositionInvalid;

    // 刪除給定位置處的元素,并返回之
    public Object remove(Position p) throws ExceptionPositionInvalid;

    // 刪除首元素,并返回之
    public Object removeFirst();

    // 刪除末元素,并返回之
    public Object removeLast();

    // 將處于給定位置的元素替換為新元素,并返回被替換的元素
    public Object replace(Position p, Object e) throws ExceptionPositionInvalid;

    // 位置迭代器
    public Iterator positions();

    // 元素迭代器
    public Iterator elements();
}
package dsa.List;

/*
 * 當作為參數(shù)的數(shù)組下標、向量的秩或列表的位置非法時,本意外將被拋出
 */

public class ExceptionPositionInvalid extends RuntimeException {
    public ExceptionPositionInvalid(String err) {
        super(err);
    }
}
package dsa.List;

public class ExceptionListEmpty extends RuntimeException {

    public ExceptionListEmpty(String err) {
        super(err);
    }

}

實現(xiàn):

package dsa.List;

import other.Position;
import dsa.Deque.DLNode;
import dsa.Vector.ExceptionBoundaryViolation;

/*
 * 基于雙向鏈表實現(xiàn)列表結(jié)構(gòu)
 */

public class List_DLNode implements List {
    protected int numElem;// 列表的實際規(guī)模
    protected DLNode header, trailer;// 哨兵:首節(jié)點+末節(jié)點
            // 構(gòu)造函數(shù)

    public List_DLNode() {
        numElem = 0;// 空表
        header = new DLNode(null, null, null);// 首節(jié)點
        trailer = new DLNode(null, header, null);// 末節(jié)點
        header.setNext(trailer);// 首、末節(jié)點相互鏈接
    }

    /**************************** 輔助方法 ****************************/
    // 檢查給定位置在列表中是否合法,若是,則將其轉(zhuǎn)換為*DLNode
    protected DLNode checkPosition(Position p) throws ExceptionPositionInvalid {
        if (null == p)
            throw new ExceptionPositionInvalid("意外:傳遞給List_DLNode的位置是null");
        if (header == p)
            throw new ExceptionPositionInvalid("意外:頭節(jié)點哨兵位置非法");
        if (trailer == p)
            throw new ExceptionPositionInvalid("意外:尾結(jié)點哨兵位置非法");
        DLNode temp = (DLNode) p;
        return temp;
    }

    /**************************** ADT方法 ****************************/
    // 查詢列表當前的規(guī)模
    public int getSize() {
        return numElem;
    }

    // 判斷列表是否為空
    public boolean isEmpty() {
        return (numElem == 0);
    }

    // 返回第一個元素(的位置)
    public Position first() throws ExceptionListEmpty {
        if (isEmpty())
            throw new ExceptionListEmpty("意外:列表空");
        return header.getNext();
    }

    // 返回最后一個元素(的位置)
    public Position last() throws ExceptionListEmpty {
        if (isEmpty())
            throw new ExceptionListEmpty("意外:列表空");
        return trailer.getPrev();
    }

    // 返回緊靠給定位置之前的元素(的位置)
    public Position getPrev(Position p) throws ExceptionPositionInvalid,
            ExceptionBoundaryViolation {
        DLNode v = checkPosition(p);
        DLNode prev = v.getPrev();
        if (prev == header)
            throw new ExceptionBoundaryViolation("意外:企圖越過列表前端");
        return prev;
    }

    // 返回緊接給定位置之后的元素(的位置)
    public Position getNext(Position p) throws ExceptionPositionInvalid,
            ExceptionBoundaryViolation {
        DLNode v = checkPosition(p);
        DLNode next = v.getNext();
        if (next == trailer)
            throw new ExceptionBoundaryViolation("意外:企圖越過列表后端");
        return next;
    }

    // 將e插入至緊靠給定位置之前的位置
    public Position insertBefore(Position p, Object element)
            throws ExceptionPositionInvalid {
        DLNode v = checkPosition(p);
        numElem++;
        DLNode newNode = new DLNode(element, v.getPrev(), v);
        v.getPrev().setNext(newNode);
        v.setPrev(newNode);
        return newNode;
    }

    // 將e插入至緊接給定位置之后的位置
    public Position insertAfter(Position p, Object element)
            throws ExceptionPositionInvalid {
        DLNode v = checkPosition(p);
        numElem++;
        DLNode newNode = new DLNode(element, v, v.getNext());
        v.getNext().setPrev(newNode);
        v.setNext(newNode);
        return newNode;
    }

    // 將e作為第一個元素插入列表
    public Position insertFirst(Object e) {
        numElem++;
        DLNode newNode = new DLNode(e, header, header.getNext());
        header.getNext().setPrev(newNode);
        header.setNext(newNode);
        return newNode;
    }

    // 將e作為最后一個元素插入列表
    public Position insertLast(Object e) {
        numElem++;
        DLNode newNode = new DLNode(e, trailer.getPrev(), trailer);
        if (null == trailer.getPrev())
            System.out.println("!!!Prev of trailer isNULL!!!");
        trailer.getPrev().setNext(newNode);
        trailer.setPrev(newNode);
        return newNode;
    }

    // 刪除給定位置處的元素,并返回之
    public Object remove(Position p) throws ExceptionPositionInvalid {
        DLNode v = checkPosition(p);
        numElem--;
        DLNode vPrev = v.getPrev();
        DLNode vNext = v.getNext();
        vPrev.setNext(vNext);
        vNext.setPrev(vPrev);
        Object vElem = v.getElem();
        // 將該位置(節(jié)點)從列表中摘出,以便系統(tǒng)回收其占用的空間
        v.setNext(null);
        v.setPrev(null);
        return vElem;
    }

    // 刪除首元素,并返回之
    public Object removeFirst() {
        return remove(header.getNext());
    }

    // 刪除末元素,并返回之
    public Object removeLast() {
        return remove(trailer.getPrev());
    }

    // 將處于給定位置的元素替換為新元素,并返回被替換的元素
    public Object replace(Position p, Object obj)
            throws ExceptionPositionInvalid {
        DLNode v = checkPosition(p);
        Object oldElem = v.getElem();
        v.setElem(obj);
        return oldElem;
    }

    // 位置迭代器
    public Iterator positions() {
        return new IteratorPosition(this);
    }

    // 元素迭代器
    public Iterator elements() {
        return new IteratorElement(this);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容