鍊錶
陣列是一種支援隨機訪問,但不支援在任意位置插入或刪除元素的資料結構。與之相對應,鍊錶支援在任意位置插入或刪除,但只能按順序依次訪問其中的元素。我們可以用乙個struct 表示鍊錶節點,其中可以儲存任意資料;另外用prev和next兩個指標指向前後相鄰的兩個節點,構成乙個常見的雙向鍊錶結構。為了避免在左右兩端或空鍊錶中訪問越界,我們建立兩個額外的節點head與tail代表鍊錶頭尾,把實際資料節點儲存在head與tail之間,來減少鍊錶便捷處的判斷,降低程式設計複雜度。
鍊錶的正規形式一般通過動態分配記憶體、指標等實現,為了避免記憶體洩露,方便除錯,使用陣列模擬鍊錶、下標模擬指標也是常見做法。兩種實現形式的參考程式:
struct node ;
node *head,*tail;
void initialize()
//在p後插入包含資料val的新節點
void insert(node *p,int val)
void remove(node *p)
void recycle()
delete tail;
}
struct nodenode[size];
int head,tail,tot;
int initialize()
int insert(int p,int val)
void remove(int p)
void clear()
鄰接表
在於鍊錶相關的諸多結構中,鄰接表是相當重要的乙個。它是樹與圖結構的一般化儲存方式,。實際上,臨界表被看做「帶有索引陣列的多個資料鏈表」構成的結構集合。在這樣的結構中儲存資料被分為若干類,每一類的資料構成乙個鍊錶。每一類還有乙個代表元素,成為該類對應鍊錶的「表頭」。所有「表頭」構成乙個表頭陣列,作為乙個可以隨機訪問的索引,從而可以通過表頭陣列定位到某一類資料對應的鍊錶。為了方便起見,我們在這裡將這類結構統稱為「臨界表」結構。
//加入有向邊(x,y),權值為z
void add(int x,int y,int z)
//訪問x出發的所有邊
for(int i=head[x];i;i=next[i])
上面的**片段用陣列模擬鍊錶的方式儲存了一張帶權有向圖的臨界表結構。對於無向圖,我們把每條無向邊看做兩條有向邊即可。有乙個小技巧是,我們在程式最開始時,初始化變數tot=1。 這樣每條無向邊看做的有向邊會成對儲存在ver和edge陣列的下標「2和3」「4和5」「6和7」……的位置上。通過對下標進行xor1的運算,就可以直接定位到與當前邊反向的邊。換句話說,如果ver[i]時第i條邊的終點,那麼ver[i xor 1]就是第i條邊的起點。 鍊錶與鄰接表
對於稀疏圖來說,m要遠遠小於n21 2 3 4 5 6 4 5 1 4 9 4 3 8 1 2 5 2 4 6 1 3 7 第一行兩個整數n m。n表示頂點個數 頂點編號為1 n m表示邊的條數。接下來m行表示,每行有3個數x y z,表示頂點x到頂點y的邊的權值為z。下圖就是一種使用鍊錶來實現鄰接...
鄰接表排序(鍊錶排序)
採取冒泡的思想,一次選取兩個,再套一層迴圈即可,但是由於在鄰接表中表頭節點和邊表節點的資料型別並不一樣,因此這相當於乙個沒有頭結點的鍊錶的排序。可以優化一下的是 如果走一遍沒有發生交換,說明已經有序了,因此就不用再進行冒泡了。可以直接跳出迴圈,減少迴圈次數。在邊表節點中,我儲存的是string型別的...
0x13 鍊錶與鄰接表
這東西我還是有點會玩的啊。鄰值查詢這東西不就是維護個前驅後繼嘛。include include include include include include using namespace std struct node a 110000 bool cmp node n1,node n2 int ...