理解链式存储
为了表示数据元素与直接后继数据元素的关系,每个数据元素除了保存自己的信息之外,还需要存储直接后继的信息。
那么我们应该怎么做呢?首先我们应该在每个数据结点中包含一个指针域(存储直接后继结点的头部地址)。
头部结点:链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息
数据结点:链表中的数组元素结点,包含了下一个数据结点的指针和自身信息
尾结点:链表中最后一个数据元素结点,后继结点为空。
//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;
}