什麼是鏈表
由一系列結點(鏈表中每一個元素稱爲結點)組成的一個有方向的數據結構體叫鏈表。其邏輯順序由指針鏈接次序實現的
順序鏈表
就我個人認爲,順序鏈表就是單項鍊表,即每個節點只有一個指針指向下一個節點。
順序鏈表的創建
要想創建一個鏈表,我們需要先創建其中的節點
#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");
}