第八课 — 线性表的链式存储结构
上节课学了线性表的顺序存储结构,可是顺序表的最大问题是插入和删除都需要移动大量的元素!
如何解决呢?
讨论:
这就是我们链式存储结构的思想。
链式存储定义:为了表示每个数据元素与其直接后继元素之间的逻辑关系 , 每个元素除了存储本身的信息外 , 还需要存储指示其直接后继的信息。
链式存储逻辑结构:n个结点链接成一个链式线性表的结构叫做链表 ,当每个结点中只包含一个指针域时 , 叫做单链表 。
链表的基本概念
表头结点
链表中的第一个结点 , 包含指向第一个数据元素的指针以及链表自身的一些信息。
数据结点
链表中代表数据元素的结点 , 包含指向下一个数据元素的指针和数据元素的信息
尾结点
链表中的最后一个数据结点 , 其下一元素指针为空 ,表示无后继。
单链表示例
链式存储结构
在C 语言中可以用结构体来定义链表中的指针域
链表中的表头结点也可以用结构体实现
删除元素操作
删除第pos 个元素的算法
判断线性表是否合法
判断插入位置是否合法
获取第pos 个元素
将第pos 个元素从链表中删除
线性表长度减1
创建可复用单链表
LinkList.h里面的类型声明:
typedef void LinkList; //类型的封装 typedef struct _tag_LinkListNode LinkListNode; //定义成结构体变量 struct _tag_LinkListNode { LinkListNode * next; }; //包含指针域的结构体
链表的创建:
typedef struct _tag_LinkList { LinkListNode header; //包含指向下一个数据元素的指针 int length; //整个链表的长度 }TLinkList; //头结点完成 LinkList * LinkList_Create(void) { /*动态分配出表头结点*/ TLinkList * ret = (TLinkList*)malloc(sizeof(TLinkList)); if( ret != NULL) { ret->length = 0; ret->header.next = NULL; //表头节点的指针域应该为空 } return ret; }
链表的长度:
LinkList * LinkList_Create(void) { TLinkList * ret = (TLinkList*)malloc(sizeof(TLinkList)); if( ret != NULL) { ret->length = 0; ret->header.next = NULL; } return ret; }
链表的插入算法:
int LinkList_Insert(LinkList* list, LinkListNode * node, int pos) { TLinkList *sList = (TLinkList *)list; int ret = (sList != NULL) && (pos >= 0) && (node != NULL); int i = 0; if (ret) { LinkListNode * current = (LinkListNode*)sList; for (i = 0; (i < pos) && (current->next != NULL); i++) { current = current->next; } node->next = current->next; current->next = node; sList->length++; } return ret; }
获取链表中的某一个位置的值:
LinkListNode* LinkList_Get(LinkList* list, int pos) { TLinkList* sList = (TLinkList*)list; LinkListNode* ret = NULL; int i = 0; if ((sList != NULL) && (0 <= pos) && (pos < sList->length )) { LinkListNode * current = (LinkListNode*)sList; for (i = 0; i < pos; i++) { current = current->next; } ret = current->next; } return ret; }
删除链表中确定位置的一个值,再构建新的链表:
LinkListNode * LinkList_Delete(LinkList* list, int pos) { TLinkList* sList = (TLinkList*)list; LinkListNode* ret = NULL; int i = 0; if ((sList != NULL) && (0 <= pos) && (pos < sList->length ) ) { LinkListNode* current = (LinkListNode*)sList; for (i = 0; i < pos; i++) { current = current->next; } ret = current->next; current->next = ret->next; sList->length--; } return ret; }
main的实现函数:
struct Value { LinkListNode hearder; int v; }; int main(void) { int i = 0; LinkList* list = LinkList_Create(); struct Value v1; struct Value v2; struct Value v3; struct Value v4; struct Value v5; v1.v = 1; v2.v = 2; v3.v = 3; v4.v = 4; v5.v = 5; LinkList_Insert(list, (LinkListNode*)&v1, 0); LinkList_Insert(list, (LinkListNode*)&v2, 0); LinkList_Insert(list, (LinkListNode*)&v3, 0); LinkList_Insert(list, (LinkListNode*)&v4, 0); LinkList_Insert(list, (LinkListNode*)&v5, 0); for (i = 0; i < LinkList_Length(list); i++) { struct Value* pv = (struct Value*)LinkList_Get(list, i); printf("%d\n", pv->v); } while (LinkList_Length(list) > 0) { struct Value* pv = (struct Value*)LinkList_Delete(list, 0); printf("%d\n", pv->v); } LinkList_Destroy(list); return 0; }
在gcc中函数的运行结果为:
欢迎加入作者的小圈子
扫描下方左边二维码加入QQ交流群,扫描下方右边二维码关注个人微信公众号并,获取更多隐藏干货,QQ交流群:859800032 微信公众号:Crystal软件学堂
作者:Liu_Jing bilibili视频教程地址:https://space.bilibili.com/5782182 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在转载文章页面给出原文连接。 如果你觉得文章对你有所帮助,烦请点个推荐,你的支持是我更文的动力。 文中若有错误,请您务必指出,感谢给予我建议并让我提高的你。 |