肥貓學習日記---數據結構與算法(三)-----鏈表

什麼是鏈表

由一系列結點(鏈表中每一個元素稱爲結點)組成的一個有方向的數據結構體叫鏈表。其邏輯順序由指針鏈接次序實現的

順序鏈表

就我個人認爲,順序鏈表就是單項鍊表,即每個節點只有一個指針指向下一個節點。

順序鏈表的創建

要想創建一個鏈表,我們需要先創建其中的節點

#define TYPE int
typedef struct Node
{
	TYPE* data;//數據域
	struct Node* next; //指針域
} Node;

Node* creat_node(data)
{
	Node* node = malloc(sizeof(Node));
	node->data = data;
	node->next = NULL;
	return node;
}

然後就可以創建鏈表了

typedef struct List
{
	Node* head;//頭指針
	Node* tail;//尾指針
	size_t size; //鏈表長度
}List;

List* creat_list()
{
	List* list = malloc(sizeof(List));
	list->head = NULL;
	list->tail = NULL;
	list->size = 0;
	return list;
}

鏈表的操作(增刪查改)

鏈表頭添加

先看代碼

void add_head(List* list,TYPE data)
{
	Node* node = creat_node(data);//創建一個新的結點
	if(0 == list->size)
	{
		list->head = node;
		list->tail = node;
	}
	else
	{
		node->next = list->head;//新結點指向頭指針所指的位子
		list->head = node;//頭指針移動到新新節點
	}
	list->size++;//鏈表長度+1
}

頭指針指向的本來結點1前面是NULL,現在結點1的前面多了一個node結點,就是頭添加。

尾添加

與頭添加差別不大

void add_tail(List* list,TYPE data)
{
	if(0 == list->size) add_head(list,data);
	Node* node = creat_node(list, data);
	list->tail->next = node;
	list->tail = node;
	list->size++;
}

頭刪除

bool del_head(List* list)
{
	if(0 == list->size) return false;
	if(1 == lsit ->size)
	{
		list->tail =NULL;//只有一個結點的話就將尾指針置空,無法訪問到該節點,就相當於刪除
	}
	Node* node = list->head;//node相當於第一個結點
	list->head = node->next;//把頭指針指向第一個結點的下一個
	free(node);//釋放第一個結點,就相當於頭刪除
	list->size--;
	return true;
}

尾刪除

參考尾添加與頭刪除

bool del_tail(List* list)
{
	if(0 == list->size) return false;
	if(1 == list->size) del_head(list);
	Node* prev = list->head;
	for(int i = 0 ; i<list->size;i++)
	{
		prev= prev->next;
	}
	free(list->tail);
	prev->next = NULL;
	list->tail = prev;
	list->size--;
	return true;
}

插入

由於這次介紹的鏈表是單向的,爲了要在一個位置插入一個新的結點,我們需要找到這個位置結點的前一個結點

bool insert_list(List* list,int index,TYPE data)
{
	if(index <0 || index >=list->size)return false;
	//如果插入位子比0小,比整個鏈表長度大,我們就返回錯誤
	if(0 == index) //在0位置插入就等於加了一個頭結點
	{
		add_head(list,data);
		return true;
		}
	Node* node = creat_node(data);
	Node* prev = list->head;
	foe(int i = 0; i <index;i++)
	{
		prev= prev->next;//找到要插入位置的前一個結點
	}
	node->next = prev->next;//prev的下一個結點就是我們要插入的位置,將node結點指向這個結點
	prev->next = node;//prev指向node結點
	list->size++;
	return true;
}

位置刪除

bool delete_index_list(List* list,int index)
{
	if(index<0 || index >= list->size) return false;
	if(0 == index)
	{
		del_head(list);//只有一個結點就相當於刪除頭結點
	}
	else if(list->size == index+1)
	{
		del_tail(list);//同上
	}
	else
	{
		Node prev = list->head;
		for(int i = 0 ; i<index;i++)
		{
			prev= prev->next;//找到要刪除結點的前一個
		}
		Node* node = prev->next;//node相當於要刪除的結點
		prev->next = node->next;//要刪除的結點的前一個結點指向要刪除的結點的下一個結點
		free(node);
		list->size--;
		return true;
	}
}

值刪除

與位置刪除核心思想相同,略微做出改變即可

bool del_data_list(List* list,TYPE data)
{
	if(data = list->head->data)
	{
		del_head(list);
		return true;
	}
	Node* prev =list->head; 
	while(NULL != prev->next)
	{
		if(prev->next->data == data)
		{
			Node* node = prev->next;
			prev->next = node->next;
			free(node);
			list->size--;
			return true;
		}
		prev=prev->next;
	}
	return false;
}

排序

我們用冒泡排序來對鏈表進行排序

void sort_list(List* list)
{
	for(Node* i = list->head; NULL!=i->next;i=i->next)
	{
		for(Node* j = i->next;NULL != j;j=j->next)
		{
			if(i->data > j ->data)
			{
				TYPE temp = i->data;
				i->data = j ->data;
				j->data = temp;
			}
		}	
	}
}

遍歷

相對之前難理解得地方而言,這個相對簡單

void show_list(List* list)
{
	for(Node* i = list->head;NULL != i->next;i=i->next)
	{
		printf("%d ",i->data);
	}
	printf("\n");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章