單向鏈表的基本實現

一、基本概念

鏈表:是一種線性表,但是並不會按線性的順序存儲數據,而是在每一個節點裏存到下一個節點的指針(Pointer)。由於不必須按順序存儲,鏈表在插入的時候可以達到O(1)的複雜度,比另一種線性表順序錶快得多,但是查找一個節點或者訪問特定編號的節點則需要O(n)的時間,而順序表相應的時間複雜度分別是O(logn)和O(1)。(來自wikipedia);

鏈表和數組的區別:

1.數組申請的是一塊連續的內存空間,並且在編譯階段就確定了空間大小,運行階段是不允許改變的,不能適應數據動態地增減。當數據增加時會造成數據越界;當數據減少時會造成內存浪費。但是數組是從棧中分配空間,對於程序員方便快速,並且數組可以根據下標直接存儲數據。在增加元素時需要移動大量元素。因此數組便於快速訪問數據,但是對於元素的插入和刪除會有很多繁瑣的操作。

2.鏈表動態地進行存儲分配,現用現申請,可以適應數據動態的增減,並且可以方便的插入、刪除數據。鏈表從堆中獲取內存,並且是物理上非連續的內存空間,能夠有效的避免一些內存碎片問題。並且可以利用鏈表來利用一些碎片化的地址空間。

二、單鏈表

單向鏈表(單鏈表)是鏈表的一種,其特點是鏈表的鏈接方向是單向的,對鏈表的訪問要通過從頭部開始,依序往下讀取。


三、鏈表的實現

1.鏈表由各個節點組成,由上圖可知,鏈表節點中包含:數據位、指針;數據位用來保存節點數據信息,指針用來指向下一個節點。則用C語言實現節點爲:

typedef struct List{

List* next;

int data;

}list;

2.鏈表的頭

鏈表頭只用來表明鏈表的入口地址;實現爲:

list* head=(list*)malloc(sizeof(list));

head->next=NULL;

3.在鏈表中添加節點

a.頭插法:

//在頭節點後添加鏈表節點
void add_node_head(list* head, int data) {
list *p= (list*)malloc(sizeof(list));
if (p == NULL) { printf("add error/n"); return; }
list* q = head->next;
head->next = p;
p->next = q;
p->data = data;

}

b.在尾部插入數據

//在鏈表的尾部添加節點

void add_node_last(list* head,int data) {
list *p = (list*)malloc(sizeof(list));
if (p == NULL) { printf("add error\n"); return; }

list* q = head;
while (q->next != NULL) {
q = q->next;
}
q->next = p;
p->next = NULL;
p->data = data;

}

c.在任意位置插入數據

//在第i個節點處添加新節點
void add_i_node(list* head,int i,int data) {
list *p = (list*)malloc(sizeof(list));
if (p == NULL) { printf("add error\n"); return; }
if (i <= 0) { printf("add i error\n"); return; }
if (i > num_node(head)) { add_node_last(head, data); return; }//如果要插入的節點大於總節點數則插入在最後
//先找到第i-1個節點處
list* q = head;
int num = 0;
while (1) {
if (num == i - 1) { break; }
q = q->next;
num++;
}
//先保存原先的第i個節點
list* node_i = q->next;

q->next = p;
p->next = node_i;
p->data = data;

}

4.刪除節點

void del_i_node(list* head,int i) {
if (i > num_node(head)) { printf("del i error\n"); return; }
if (i < 1 ) { printf("del i error\n"); return; }

//先找到第i-1個節點處
list* q = head;
int num = 0;
while (1) {
if (num == i - 1) { break; }
q = q->next;
num++;
}

//先保存原先的第i個節點
list* node_i = q->next;

q->next = q->next->next;
free(node_i);//手動釋放申請的內存空間

}

5.鏈表的遍歷

//遍歷整個鏈表
void list_see(list* head) {
list* q = head;
int num = 0;
while (q->next != NULL) {
q = q->next;
num++;
printf("node_%d = %d.\n",num,q->data);
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章