鍊錶和陣列作為演算法中的兩個基本資料結構,在程式設計過程中經常用到。儘管兩種結構都可以用來儲存一系列的資料,但又各有各的特點。
陣列的優勢,在於可以方便的遍歷查詢需要的資料。在查詢陣列指定位置(如查詢陣列中的第4個資料)的操作中,只需要進行1次操作即可,時間複雜度為o(1)。但是,這種時間上的便利性,是因為陣列在記憶體中占用了連續的空間,在進行類似的查詢或者遍歷時,本質是指標在記憶體中的定向偏移。然而,當需要對數組成員進行新增和刪除的操作時,陣列內完成這類操作的時間複雜度則變成了o(n)。
鍊錶的特性,使其在某些操作上比陣列更加高效。例如當進行插入和刪除操作時,鍊錶操作的時間複雜度僅為o(1)。另外,因為鍊錶在記憶體中不是連續儲存的,所以可以充分利用記憶體中的碎片空間。除此之外,鍊錶還是很多演算法的基礎,最常見的雜湊表就是基於鍊錶來實現的。基於以上原因,我們可以看到,鍊錶在程式設計過程中是非常重要的。本文總結了我們在學習鍊錶的過程中碰到的問題和體會。
接下來,我們將對鍊錶進行介紹,用c語言分別實現:鍊錶的初始化、建立、元素的插入和刪除、鍊錶的遍歷、元素的查詢、鍊錶的刪除、鍊錶的逆序以及判斷鍊錶是否有環等這些常用操作。並附上在visual studio 2013中可以執行的**供學習者參考。
說到鍊錶,可能有些人還對其概念不是很了解。我們可以將一條鍊錶想象成環環相扣的結點,就如平常所見到的鎖鏈一樣。鍊錶內包含很多結點(當然也可以包含零個結點)。其中每個結點的資料空間一般會包含乙個資料結構(用於存放各種型別的資料)以及乙個指標,該指標一般稱為next,用來指向下乙個結點的位置。由於下乙個結點也是鍊錶型別,所以next的指標也要定義為鍊錶型別。例如以下語句即定義了鍊錶的結構型別。
定義鍊錶結構體型別:
//鍊錶的型別
struct linklist
;
鍊錶初始化:
linklist* init()
headnode->val = 0;
headnode->next = null;
return headnode;
}
這裡引申一下,此處例程中返回的鍊錶指標為該鍊錶的頭結點,相對應的還有乙個頭指標的概念。頭指標內只有指標的元素,並沒有資料元素,但頭結點除了指標還有資料。
頭指標就是鍊錶的名字,僅僅是個指標而已。頭結點是為了操作的統一與方便而設立的,放在第乙個有效元素結點(首元結點)之前,其資料域一般無意義(當然有些情況下也可存放鍊錶的長度、用做監視哨等等)。一般情況下見到的鍊錶的指標多為頭指標,但最近在乙個程式設計師程式設計**leetcode中發現,題目中所給的鍊錶一般是首元結點作為第乙個元素,而不是頭指標。
鍊錶建立
鍊錶建立的步驟一般使用給定的頭指標以及需要初始化的資料序列作為輸入引數,本文使用陣列作為輸入資料序列。在下面的例程中,先將首元結點使用陣列第乙個元素初始化,再在首元結點之後建立新的鍊錶結點賦值陣列內餘下的資料。具體實現如下:
void creat_linklist(linklist *headnode,int *indata,int data_num)
current->next = null;
}}
顯示鍊錶
//顯示鍊錶
void show_linklist(linklist *headnode)
}
插入鍊錶節點
鍊錶建立完之後,下面我們將介紹如何向鍊錶內插入結點。一般新增結點可以分為兩類:一類是在鍊錶尾部插入;另一類為在中間插入。
鍊錶結尾新增結點的步驟就是新建乙個鍊錶結點,將其鏈結到當前鍊錶尾指標。
假設乙個鍊錶內存在幾個幾點a1,a2,a3,a4….,當根據要求需要在指定位置之後(比如a2結點)插入乙個新結點時。首先我們需要新建立乙個結點nodetoinsert,然後將新結點的next指向a3,並且將a2的next指標指向新建立的結點nodetoinsert,切記操作順序不要改變。如果操作順序變換一下,先將a2的next指向了新建立的結點,那麼我們就丟失了a3的定址方式。因此,在將a2的next指向其他任何地方之前,請務必將a3的位址存在nodetoinsert或者某個新建節點內。
//插入鍊錶節點
bool insert_list(linklist *headnode, int indata_dex, int data)
linklist *insert = (linklist *)malloc(sizeof(linklist));//建立節點
if (insert == null)
insert->val = data;
insert->next = current->next;//將原本位置的位址,放在插入元素的後面
current->next = insert;//
return true;
}
刪除鍊錶節點
對應於插入鍊錶結點,鍊錶的基本操作中同樣也有刪除鍊錶結點。刪除結點包括刪除指定位置的結點和指定元素的結點。其基本原理都是先鎖定待刪除的結點的位置,然後將該結點的後置結點鏈結到前置結點的next指標處。這樣中間這個結點即我們要刪除的結點就從原來的鍊錶中脫離開來。相對於原來的鍊錶,即刪除了該結點。
//刪除鍊錶節點
bool delect_link_list(linklist * headnode, int index, int *datatodel)
linklist* delete = (linklist*)malloc(sizeof(linklist));
delete = current->next;
*datatodel = current->next->val;
printf("delect is %d", *datatodel);
current->next = current->next->next;
free(delete);
return true;
}
獲取鍊錶的長度
int length_list(linklist* headnode)
return i;
}
獲取鍊錶的元素位置
//獲取鍊錶的元素
int locate_val(linklist* headnode, int data_locate)
current = current->next;
i++;
} return -1;//沒有該值
}
銷毀鍊錶
//鍊錶置空,銷毀鍊錶
bool destory_list(linklist*headnode)
headnode->next = null;
return true;
}
判斷鍊錶是否有環
//鍊錶判斷是否有環
bool islistloop(linklist*headnode)
else
if (slow==fast)
}return false;
}
參考**: 資料結構(一)鍊錶
include using namespace std struct linknode 鍊錶結點的定義 void createlink linknode head 後插法建立鍊錶演算法 void show linknode head 遍歷鍊錶演算法 void deletelinknode linkn...
資料結構之鍊錶 一
線性表分為順序儲存結構和鏈式儲存結構2種。順序儲存結構的特點 任何乙個元素都可以進行隨即訪問,訪問速度高。但不適合瀕繁的插入和刪除操作。鏈式儲存結構 鍊錶 不可以隨即訪問元素。但適合頻繁的插入和刪除操作。乙個靜態鍊錶的例子 include struct node typedef struct nod...
資料結構之鍊錶(一)
很多人,一接觸到資料結構就難懂,就說有難度,還有就說,鍊錶有什麼用?今天我就詳細的說下,這個鍊錶有什麼用。一 鍊錶介紹 1 鍊錶有位址不連續的結點序列,必須通過指標相互連線。2 鍊錶的分類 1 單向線性鍊錶 每個節點中除了儲存資料結構內容以外,還需要儲存指向下乙個節點的指標,叫做後指標。最後乙個節點...