用物件的多重陣列實現雙鏈表

2021-06-28 12:12:06 字數 3352 閱讀 7809

在有些語言(例如fortran)中不提供指標與物件資料型別,那麼該如何實現雙鏈表呢?我們將介紹運用陣列和陣列下標在邏輯上來構造雙鏈表,讓它表現的就像用指標實現的一樣自然。

物件的多重陣列表示

如下圖是乙個用陣列實現的雙鏈表的邏輯圖:

對一組具有相同域的物件,每乙個域都可以用乙個陣列來表示。上圖說明了如何用三個陣列實現雙鏈表。動態幾何的關鍵字儲存在陣列key中,而指標域儲存在prev和next中。對於乙個給定的下標x,key[x],prev[x],next[x]久共同組成了鍊錶中的乙個物件,即節點,在這種解釋下,乙個指標x即為指向陣列key,prev和next的共同下標。

在上圖的鍊錶中,關鍵字4的物件在關鍵字為16的物件的後面。對應地,關鍵字出現在key[2]上,關鍵字16出現在key[5]桑,故有next[5] = 2;prev[2] = 5.雖然常熟nil(/)出現在表尾的next域和表頭的prev域中,但我們通常用乙個不指向陣列中任何乙個位置的整數(在我們的實現**中,取noexist為-1)來表示之。另外變數l儲存了表頭元素的下標。

分配和釋放物件

為向乙個用雙鏈表表示的動態集合中插入乙個物件,需要分配乙個當前指向鍊錶表示中未被使用的物件的指標,即下標。那麼,我們需要對鍊錶中未被使用的空間進行管理,從而方便分配。

在這裡,我們利用指標域把自由物件組織成乙個單鏈表,成為自由鍊錶。自由鍊錶僅用到next域,其中存放著下乙個自由物件的下標,此煉表頭儲存在free中。當鍊表l非空時,自由鍊錶和雙鏈表l將相互交錯到一起,如下圖所示。但是,乙個空間要麼存在於自由鍊錶中,要麼存在於雙鏈表中,不可能同時存在於兩者之中。

a)為鍊錶初始時;b)表示插入關鍵字25之後的結果;c)表示刪除關鍵字16的結果。

自由類似於乙個棧,每次分配時取用的空間都是從自由煉表頭摘取,即最近被釋放的那個,下面是分配和**自由物件的函式。

獲得乙個自由物件

template inline size_t list::getfree()

size_t index = free;

free = next[index];

return index;

}

釋放乙個節點

void addfree(size_t index)

在空間足夠時,上面兩個過程的時間代價均為o(1),因而很實用。

多重陣列表示的雙鏈表的具體實現

我們

都知道,普通的陣列都有乙個缺陷,即不能夠動態的改變大小,每次都必須提前分配足夠的空間。對於用多重陣列來實現雙鏈表,並且要表現的像用指標實現的一樣自然,首要解決的就是動態分配以及**空間的問題。

在上面的分配過程getfree中我們已經看到採用的策略是一旦空間不夠,即馬上分配兩倍於原來的大小,並複製原先內容到新空間,然後釋放舊空間。

解決了這個問題,那麼接下來的實現就很簡單了,在邏輯上我們就可以將這兩個鍊錶free和l改變成我們熟悉的樣子來理解插入和刪除等過程。

實現源**:

#include#define noexist 0x7fffffff

using namespace std;

template class list;

template ostream& operator<

template class list

void newlist(size_t n)

void deletelist(size_t *p, t *k, size_t *n)

void copylist(size_t *p, t *k, size_t *n, size_t s)

void setfree(size_t start_index)

public:

list() :free(noexist), head(noexist), list_size(8)//-1表示空,最初鍊錶有8個空間

list(t *beg, t *end) :list()

void setdata(size_t index, const t &t)

t getdata(size_t index)const

void insert(const t&);

void insert(t*, t*);

size_t locate(const t&);

void erase(const t&);

void erase(size_t);

void edit(const t&, const t&);

bool empty() //鍊錶是否為空

~list()

//bool full()

};template inline size_t list::getfree()

size_t index = free;

free = next[index];

return index;

}template void list::insert(const t &t)

else }

template void list::insert(t *beg, t *end)

template size_t list::locate(const t &t)

template void list::erase(size_t index)

addfree(index);

}template void list::erase(const t &t)

template void list::edit(const t &old_key, const t &new_key)

key[index] = new_key;

}template ostream& operator<

return out;

}int main()

; listlst(a,a + 6);

cout << lst << endl << endl;

for (int i = 10; i != 20; ++i)

lst.insert(i);

cout << lst << endl << endl;

for (int i = 1; i != 1000; ++i)

cout << lst << endl;

getchar();

return 0;

}



js用遞迴改寫多重陣列

後台給返回的資料是這樣的 現在想得到這樣的資料 而且後台給的陣列中並不確定是幾層的,所以這裡必須用到遞迴函式。用了下面的 let routerarr json.parse json.stringify value function formatroutes routerarr routerarr.f...

陣列實現雙鏈表

之前寫了陣列實現單鏈表,提到了陣列實現鍊錶比指標實現最大的優點就是快,可以隨機訪問,而且不用new節點。在圖論的題目裡用到鄰接表,往往都是用陣列實現。陣列實現雙鏈錶比單鏈表就多了一些對於左指標的操作。為了實現的方便,不像在單鏈表實現裡用乙個額外的變數head去記錄鍊錶的頭節點。而是直接用兩個哨兵節點...

演算法雜談 用雙鏈表實現洗牌

思路 首先構建雙鏈表,把54張牌串聯起來!然後迴圈隨機抽牌。第一次從54張牌中抽取一張,第二次從剩餘的53張牌中抽取一張,以此內推,直到剩餘的牌為0 include include include include include 54張牌,s表示10,x表示小王,d表示大王 char pai 儲存洗...