c語言實現單向鏈表和雙向鏈表

鏈表:它是一種物理儲存單元上的非連續,非順序的儲存結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現。鏈表由一系列結點組成,每個結點包括兩部分,一個是儲存數據元素的數據域,一個是儲存下一個結點地址的指針域

順序表:順序表是使用數組存儲線性的元素,因爲邏輯上相鄰的元素物理上也相鄰,所以插入刪除需要移動後面的所有元素,但是鏈表使用指針來表達後面結點的邏輯關係,所以插入和刪除只需要修改指針即可。

鏈表可以解決幾個數組無法解決的問題:數組無法儲存多種類型的數據,數組中元素的個數無法改變,數組移動元素時其他元素也要跟着移動

鏈表實現原理: 頭指針指向了鏈表的第一個節點,然後第一個節點中的指針指向了下一個節點,下一個節點指向下下個節點,直到最後一個節點需要指向Null

#include <stdio.h>
#include <stdlib.h>

struct linklist_node{  // 以結構的形式來聲明一個鏈表節點
	int data;  // 節點的數據域,用於存儲數據
	struct linklist_node * next;  // 節點的指針域,指向下一個類型爲linklist_node的節點
};
typedef struct linklist_node single_node; // 這裏節點結構被聲明爲single_node了

// 下面是創建一個鏈表節點的函數
single_node * create_single_node(int data){
	single_node * node = NULL;  // 首先定義一個指向節點類型的指針
	node = (single_node *)malloc(sizeof(single_node));  // 爲node動態分配內存
	memset(node, 0, sizeof(single_node)); // 爲新分配的內存進行初始化
	
	node -> data = data;  // 數據域賦值
	node -> next = NULL;  // 指針域賦值,指向空
	return node;  // 返回一個指向node類型的指針
}

// 下面是主函數
int main(void){
	int data = 1;
	single_node * node_ptr = create_single_node(data);  // 創建一個節點,得到一個節點指針
	free(node_ptr); // 釋放內存
	return 0;
}

上面的node_ptr其實是定義的一個頭指針,然後它指向擁有數據域和指針域的節點,然後該節點指向NULL。


接下來,我們首先用一段主函數來描述我們想用各種函數完成的事兒

int main(int argc, char **argv){
	int i;
	single_node * header = create_single_node(0); // 創建第一個節點
	for(i = 1; i < 10; i++){
		tail_insertion(header, create_single_node(i));
	} // 尾插一堆元素
	top_insertion(header, create_single_node(100);
	print_node(header);  // 打印所有的元素
	delete_single_node(header, 5);  // 刪除指定值的元素
}

鏈表的尾插:

void tail_insertion(single * header, single * new){
	single_node * current;
	current = header;
	while(current->next != NULL){
		current = current->next;  // 這裏直到找到最後一個節點
	}
	current->data = new->id;
	current->next = NULL;
}

鏈表的頭插:

void top_insertion(single_node * header, single * new){
	single_node * current;
	current = header;
	new -> next = current -> next;  // 這裏要先把新節點的下一個指向第二個節點,不然可以反過來就知道錯誤了
	current -> next = new;
}	

鏈表元素的打印:

void print_node(single_node * header){
	single_node * current = header;
	current = current -> next;  // 獲取第一個節點的位置,因爲header是頭指針沒有值的
	while(current -> next != NULL){
		printf("data is %d", current -> data);
		current = current -> next;
	}
}

刪除鏈表中的元素:

int delete_single_node(single_node * header, int data){
	single_node * current = header;  // 設置當前位置爲頭指針
	single_node * prev = NULL;  // 記錄前一個節點的位置,最一開始爲空
	while(current -> next != NULL){
		prev = current;  // 第一步將prev設置爲頭指針了
		current = current -> next;  // 第一步將current設置爲第一個節點了
		if(current -> data == data){
			if (current -> next == NULL){   // 噹噹前節點爲最後一個節點時,該節點next應該爲空
				prev -> next = NULL;
			}
			else{  // 這是普通節點
				prev -> next = current -> next;
			}
			free(p);
		}
	}
	return 0}

雙向鏈表

單鏈表存在一定的弊端,查找數據和刪除數據的時候比較麻煩,而雙鏈表就可以解決這個弊端,雙鏈表既可以往前遍歷,也可以往後遍歷;所以雙鏈表的節點相當於data加上兩個指針,一個指向前面的節點,一個指向後面的節點。

struct double_linklist_node{
	int data;
	struct double_linklist_node * prev;
	struct double_linklist_node * next;
}
typedef struct double_linklist_node single_node;

single_node * create_single_node(int data){haishi shnme size (of 
	single_node * node = (single_node *)malloc(sizeof(single_node));
	memset(node, 0, sizeof(single_node));
	node -> data = data;
	node -> prev = NULL;
	node -> next = NULL;
	return node;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章