理解鏈式存儲
爲了表示數據元素與直接後繼數據元素的關係,每個數據元素除了保存自己的信息之外,還需要存儲直接後繼的信息。
那麼我們應該怎麼做呢?首先我們應該在每個數據結點中包含一個指針域(存儲直接後繼結點的頭部地址)。
頭部結點:鏈表中的第一個結點,包含指向第一個數據元素的指針以及鏈表自身的一些信息
數據結點:鏈表中的數組元素結點,包含了下一個數據結點的指針和自身信息
尾結點:鏈表中最後一個數據元素結點,後繼結點爲空。
//LinkList.h
#pragma once
typedef void LinkList;
//數據元素結點
typedef struct tag_LinkListNode
{
struct tag_LinkListNode *next;//指針域
}TLinkListNode;
//創建鏈表
LinkList *LinkList_Creat();
//銷燬鏈表
void LinkList_Destroy(LinkList*list);
//清空鏈表初始化鏈表
void LinkList_Clear(LinkList *list);
//獲取鏈表長度
int LinkList_GetLength(LinkList *list);
//插入結點
int LinkList_inster(LinkList *list, TLinkListNode *node, int pos);
//獲取指定位置結點
TLinkListNode *LinkList_Get(LinkList *list, int pos);
//刪除指定位置結點
TLinkListNode *LinkList_Delete(LinkList *list, int pos);
插入元素的操作
假設pos = 3表示在鏈表中下標爲3的位置插入一個節點。
提供一個輔助指針current,通過循環跳轉到pos-1的位置,current->next是current當前指向結點的後繼結點,那麼我們應該怎麼操作呢?
首先我們應該把Node結點的後繼指針指向current當前結點的後繼結點,其次current的後繼指針指向插入的結點,這樣就完成了鏈接。
node->next = current->next
curren->next = node
獲取指定元素的操作
這裏我們需要注意,指向頭部結點的指針移動n次和第n個元素之間的關係
假設我們要獲取pos = 3(索引下標)位置上的結點,那麼輔助指針current通過循環跳轉應該跳轉到pos-1的位置上,這樣我們要獲取的結點應該是current後繼指針指向的結點:current->next
刪除指定位置元素操作
刪除指定結點同樣要注意指向頭部結點的指針移動n次和第n個元素之間的關係
假設我們要刪除pos = 3位置上的結點,我們需要讓輔助指針current通過循環跳轉到pos-1的位置上
首先提供一個輔助指針結點用來存放要刪除的結點node,其次讓輔助指針current的後繼指針指向要刪除結點node的後繼結點。
node = current->next;
current->next = node->next
//LinkList.c
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "LinkList.h"
//鏈式線性表
typedef struct tag_LinkList
{
TLinkListNode header;//頭部結點
int length;//線性表長度
}TLinkList;
//創建鏈式線性表
LinkList * LinkList_Creat()
{
TLinkList *list = NULL;
list = (TLinkList *)malloc(sizeof(TLinkList));//給鏈式線性表分配堆內存
if (list == NULL)
{
printf("LinkList_Creat err: list = NULL");
return NULL;
}
memset(list, 0, sizeof(TLinkList));//鏈式線性表初始化(分配了內存要負責)
list->length = 0;
list->header.next = NULL;
return list;
}
//銷燬鏈式線性表
void LinkList_Destroy(LinkList * list)
{
if (list == NULL)
{
printf("LinkList_Destroy err: list = NULL");
return;
}
free(list);//直接釋放鏈式線性表堆內存
printf("LinkList_Destroy finished \n");
return;
}
//清空線性表
void LinkList_Clear(LinkList * list)
{
TLinkList *temp = NULL;
if (list == NULL)
{
printf("LinkList_Clear err: list = NULL");
return;
}
temp = (TLinkList *)list;//類型轉換
temp->length = 0;//重置長度
temp->header.next = NULL;//頭結點置空
return;
}
//獲取鏈表長度
int LinkList_GetLength(LinkList * list)
{
TLinkList *temp = NULL;
if (list == NULL)
{
printf("LinkList_GetLength err: list = NULL");
return -1;
}
temp = (TLinkList *)list;//類型轉換
return temp->length;//返回鏈表長度
}
//在指定位置插入結點
int LinkList_inster(LinkList * list, TLinkListNode * node, int pos)
{
TLinkList *temp = NULL;
int i = 0;
if (list == NULL || node == NULL || pos < 0)
{
printf("LinkList_inster err: list = NULL || node = NULL || pos < 0");
return -1;
}
temp = (TLinkList *)list;//類型轉換
TLinkListNode * current = &(temp->header);//當前結點
for (i = 0; i < pos && node->next != NULL; i++)//跳轉到插入位置的前一個結點位置處
{
current = current->next;
}
node->next = current->next;//插入節點的後繼指針指向當前結點的後繼結點
current->next = node;//當前結點的後繼指針指向要插入的結點
temp->length++;//鏈表長度+1
return 0;
}
//獲取鏈表指定位置結點
TLinkListNode * LinkList_Get(LinkList * list, int pos)
{
TLinkList *temp = NULL;
int i = 0;
if (list == NULL || pos < 0)
{
printf("LinkList_Get err: list = NULL || pos < 0");
return NULL;
}
temp = (TLinkList *)list;//類型轉換
TLinkListNode * current = &(temp->header);//當前結點
for (i = 0; i < pos ; i++)//循環跳轉到需要獲取結點的前一個結點處
{
current = current->next;
}
return current->next;//返回需要獲取的結點
}
//刪除鏈表指定位置結點
TLinkListNode * LinkList_Delete(LinkList * list, int pos)
{
TLinkList *temp = NULL;
int i = 0;
if (list == NULL || pos < 0)
{
printf("LinkList_Get err: list = NULL || pos < 0");
return NULL;
}
temp = (TLinkList *)list;//類型轉換
TLinkListNode *current = &(temp->header);//輔助指針指向頭部結點
TLinkListNode *ret = NULL;//輔助指針存放需要刪除的結點
for (i = 0; i < pos; i++)//循環跳轉到要刪除幾點的前一個結點處
{
current = current->next;
}
ret = current->next;//臨時存放要刪除的結點
current->next = ret->next;//當前結點的後繼指針指向要刪除結點的後繼節點處
temp->length--;//鏈表長度-1
return ret;//返回要刪除的結點
}
//測試代碼
#pragma warning(disable : 4996)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "LinkList.h"
typedef struct tag_Teacher
{
TLinkListNode node;
int age;
char *name;
}Teacher;
int main(int argc, char** argv)
{
Teacher t1, t2, t3, t4, t5;
t1.age = 20;
t1.name = "zhangsan";
t2.age = 21;
t2.name = "lisi";
t3.age = 22;
t3.name = "wangwu";
t4.age = 23;
t4.name = "zhaoliu";
t5.age = 24;
t5.name = "wangqi";
LinkList *list = NULL;
list = LinkList_Creat();
if (list == NULL)
{
printf("LinkList_Creat err: list = NULL");
return -1;
}
int i, ret = 0;
//尾插法
ret = LinkList_inster(list, (TLinkListNode *)&t1, LinkList_GetLength(list));
ret = LinkList_inster(list, (TLinkListNode *)&t2, LinkList_GetLength(list));
ret = LinkList_inster(list, (TLinkListNode *)&t3, LinkList_GetLength(list));
ret = LinkList_inster(list, (TLinkListNode *)&t4, LinkList_GetLength(list));
ret = LinkList_inster(list, (TLinkListNode *)&t5, LinkList_GetLength(list));
printf("LinkList length = %d\n", LinkList_GetLength(list));
for (i = 0; i < LinkList_GetLength(list); i++)
{
Teacher *t = (Teacher *) LinkList_Get(list, i);
printf("age = %d,name = %s\n", t->age, t->name);
}
system("pause");
return 0;
}