鏈表的定義
鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。 相比于線性表順序結構,操作復雜。
單向鏈表.jpg
模擬鏈表
結構體模擬鏈表
先用一個結構體來表示鏈表的結點類型
struct node{
int data;
struct node *next;
};
那么循環輸入幾個數存入鏈表中就可以這樣寫
head = NULL; // 頭指針的初始為空
for (i = 0; i <= n; i++) {
scanf("%d",&a);
// 動態申請一個空間,用來存放一個結點,并用臨時指針p指向這個結點
p = (struct node*)malloc(sizeof(struct node));
// 將數據存儲到當前結點的data域中
p->data = a;
// 設置當前結點的后繼指針指向空,也就是當前結點的下一個結點為空
p->next = NULL;
if (head == NULL) {
// 如果這是第一個創建的結點,則將頭指針指向這個結點
head = p;
}else{
// 不是第一個創建的結點,則將上一個結點的后繼指針指向當前結點
q ->next = p;
}
p = q; // 指針q也指向當前結點
}
那么在這個鏈表中間插入一個數的話又該如何操作呢?首先用一個臨時指針t從鏈表的頭部開始遍歷,等到指針t的下一個結點的值比插入的數大的時候,就將插入的數插入到中間即可。
t= head; // 從鏈表頭部開始遍歷
while (t != NULL) {// 沒有到達鏈表尾部的時候循環
// 如果當前結點是最后一個結點或者下一個結點的值大于待插入數的時候插入
if (t ->next == NULL || t ->next ->data >a) {
// 動態申請一個空間,用來存放新增的結點
p = (struct node*)malloc(sizeof(struct node));
p->data = a;
// 新增結點的后繼指針指向當前結點的后繼指針所指向的結點
p->next = t->next;
// 當前結點的后繼指針指向新增結點
t->next = p;
break;
}
t = t->next;
}
數組模擬單向鏈表
鏈表中的每一個結點只有兩個部分。我們可以用一個數組data來存儲序列中的每一個數。那么每一個數的右邊我們就需要再用一個數組right來存放序列中每一個數。
數組模擬單向鏈表.png
現在需要在8前面插入一個6,只需要將6直接存放在數組data的末尾data[10] = 6。接下來只需要將right[3]改為10,表示新序列中3號元素右邊的元素存放在data[10]中。再將right[10]改為4,表示新序列中10號元素右邊的元素存放在data[4]中。
插入一個數.png
現在我們可以通過right數組就可以從頭到尾遍歷整個序列了。下面是完整代碼:
int main(int argc, const char * argv[]) {
arrayMethod();
getchar();
getchar();
return 0;
}
void arrayMethod(){
int data[101],right[101];
int i, n, t, len;
scanf("%d",&n);
for (i = 1; i<= n; i++) {
scanf("%d",&data[i]);
}
len = n;
//初始化數組right
for (i = 1; i <= n; i++) {
if (i != n) {
right[i] = i+1;
}else{
right[i] = 0;
}
}
// 直接在data數組末尾添加一個數
len++;
scanf("%d",&data[len]);
// 從鏈表的頭部開始遍歷
t = 1;
while (t != 0) {
//如果當前結點下一個結點的值大于帶插入數,將數插入到中間
if (data[right[t]] > data[len]) {
// 新插入數的下一個結點標號等于當前結點的下一個編號
right[len] = right[t];
// 當前結點的下一個結點編號就是新插入的編號
right[t] = len;
break;
}
t = right[t];
}
// 輸出鏈表
t =1;
while (t != 0) {
printf("%d",data[t]);
t = right[t];
}
}
輸入:
Snip20161223_6.png
結果為:
Snip20161223_7.png