一點 線性表

2021-08-09 00:27:01 字數 4881 閱讀 5143

線性表

線性表的定義:由成為元素的資料項組成的一種有限且有序的序列。

這裡的有序是指每個元素都有自己的位置,而非元素按其值大小排序,當線性表不包含任何元素時,稱為空表,元素數目稱為線性表的長度,開始結點稱為表頭,結尾結點稱為表尾,表中元素的值和它的位置可以有聯絡也可以無聯絡。

線性表的c++抽象類宣告:

template class list       // protect assignment

list(const list&) {} // protect copy constructor

public:

list() {} // default constructor

virtual ~list() {} // base destructor

// clear contents from the list, to make it empty.

virtual void clear() = 0;

// insert an element at the current location.

// item: the element to be inserted

virtual void insert(const e& item) = 0;

// remove and return the current element.

// return: the element that was removed.

virtual e remove() = 0;

// set the current position to the start of the list

virtual void movetostart() = 0;

// set the current position to the end of the list

virtual void movetoend() = 0;

// move the current position one step left. no change

// if already at beginning.

virtual void prev() = 0;

// move the current position one step right. no change

// if already at end.

virtual void next() = 0;

// return: the number of elements in the list.

virtual int length() const = 0;

// return: the position of the current element.

virtual int currpos() const = 0;

// set current position.

// pos: the position to make current.

virtual void movetopos(int pos) = 0;

// return: the current element.

virtual const e& getvalue() const = 0;

};

順序表實現方式:

template // array-based list implementation

class alist : public list

~alist() // destructor

void clear()

// insert "it" at current position

void insert(const e& it)

assert(listsize < maxsize, "list capacity exceeded");

listarray[listsize++] = it;

} // remove and return the current element.

e remove()

const e& getvalue() const

link(link* nextval =null)

};

由於採取使curr指向前乙個元素,以便輕鬆地在curr之後插入新元素,所以需要乙個特殊的空表頭結點,使head指向它,這樣就可以進行正常的新增刪除操作,而在初始化的時候,就將head,tail,curr均指向該空結點。

template class llist: public list

void removeall()

}public:

llist(int size=defaultsize) // constructor

~llist() // destructor

void print() const; // print list contents

void clear() // clear list

// insert "it" at current position

void insert(const e& it)

tail = tail->next = new link(it, null);

cnt++;

} // remove and return current element

e remove()

void movetostart() // place curr at list start

void movetoend() // place curr at list end

// move curr one step left; no change if already at front

void prev()

// move curr one step right; no change if already at end

void next()

int length() const // return length

// return the position of the current element

int currpos() const

// move down list to "pos" position

void movetopos(int pos)

const e& getvalue() const

};

remove函式中為了防止「丟失」被刪除節點的記憶體,因此先將要刪除的指標指向臨時指標itemp,然後呼叫delete函式釋放被刪除結點占用的記憶體。

鍊錶中除了prev一般需要θ(n)時間,而movetopos(i)需要θ(i)時間以外,其餘操作只需θ(1)時間。

而為了簡化建立和刪除結點的操作,在link類中新增可以自己管理的可利用空間表,因此可以採用c++操作符過載方法來替代new和delete

template class link 

link(link* nextval =null)

void* operator new(size_t)

void operator delete(void* ptr)

};template link* link::freelist = null;

順序表的缺點顯而易見,需要預先設定長度,如果未用完,造成浪費,如果過多,則裝不下,相比之下,鍊錶更加靈活;順序表的優點在於,每乙個元素沒有造成空間浪費,而鍊錶則優於儲存指標資訊,而造成了結構性開銷(並非儲存真正資料的資訊所佔空間)。綜上可知,在未知元素多少的情況下,鍊錶更好,在確定元素多少時,順序表更節省空間。

而具體的選擇,可以根據以下這個簡單的公式來判斷:

n>de/(p+e)

n:線性表中當前元素的數目  p:指標的儲存單元大小  e:資料元素的儲存單元大小  d:陣列中儲存的線性表元素的最大數目

那麼可知順序表的空間需求為:de,而鍊錶的空間需求則與n有關:n(p+e),由此可以得到上述公式,並得到n的臨界值de(p+e),當n大於此值時,順序表更優,反之則反。

在鍊錶的基礎上,有雙鏈表可以進行從前向後和從後向前的雙向操作,而僅需要新增乙個prev指標用於指向前一結點和對部分函式的操作做些許調整即可。

此處,考慮到在鍊錶實現時,新增空表頭結點以更好的實現從前向後的功能,這裡雙向鍊錶相應的就需要在尾部再增加乙個空表尾結點(tail指向它),以更好的實現從後向前的功能。因此,在初始化的時候head和tail分別指向頭尾空結點,而next與prev則分別指向尾頭空結點。

ps:在單項鍊表實現中,仍可採用更符合直觀邏輯的curr指向當前結點,而非當前結點的前驅結點,但此時造成的問題是前驅結點的next無法更新,可採用以下替代方案:在當前結點之後新增乙個結點, 將當前元素值複製到其中,同時將新值插入到那個老的當前結點之中。

對此方案的理解,可以稱之為,老人傳魂,在此處可以通過日本一恐怖短片《奶奶》來更好的理解。

我們首先假稱結點值為 魂,而結點為 身體,結點值放入結點中則為完整的人,魂與身體可以分離並交換。

在這裡就直接講述《奶奶》這個故事來理解這個方案:

奶奶病危,這時,奶奶請求與孫女交換身體,去實現自己的遺願,孫女心軟同意,讓奶奶佔據了自己的身體,而自己的魂則代替奶奶存在於病危的身體中,受苦。

可以將奶奶病危,看作要添入新結點,這時,通過將老結點的值即奶奶的魂,傳到新結點即新身體之中,便可以讓老結點值一直存在,而從外界來看,依然是加入了新值即「奶奶」「正常」死去,「孫女」健康長大。

由於這個原因,此處也不需要再有空表頭結點了,相反,需要空表尾結點,不然,便永遠也無法刪除掉最後乙個結點,因為它會不斷地將自己放到最後。所以需要有乙個預備的結點,才可以停止讓最後乙個結點「金蟬脫殼」。

刪除線性表節點 線性表

submit 81 solved 66 submit status web board 已知長度為n的線性表a採用順序儲存結構,請寫一時間複雜度為0 n 空間複雜度為0 1 的演算法,該演算法刪除線性表中所有值為item的資料元素。o 1 表示演算法的輔助空間為常量 輸入 n 6 輸入資料 1 2 ...

線性表知識點

具有相同 每個元素所佔空間一樣大 資料型別的n個資料元素的有限序列,n為表長,當n 0為空表 ai i為位序 a1 表頭,an表尾 直接前驅 直接後繼 初始化 分配記憶體空間 銷毀 釋放記憶體空間 插入 指定位置插入指定元素,注意!儲存空間是否滿,插入元素要跟前後相鄰 刪除 刪除指定並用e返回被刪除...

資料結構 線性表之單向鍊錶 一點一滴

單向鍊錶 單鏈表 是鍊錶的一種,其特點是鍊錶的鏈結方向是單向的,對鍊錶的訪問要通過順序讀取從頭部開始。單向鍊錶的資料結構可以分為兩部分 資料域和指標域,資料域儲存資料,指標域指向下乙個儲存節點的位址。分為動態單向鍊錶和靜態單向鍊錶。單向鍊錶也可以根據是否帶頭節點分為帶頭節點結構和無帶頭節點結構。我們...