在有些語言(例如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 儲存洗...