线性表(List)---链式存储结构(单向链表)
来源:互联网 发布:淘宝老顾客回购率 编辑:程序博客网 时间:2024/05/14 13:25
单向链表设计与实现
链式存储的基本介绍
链式存储定义: 为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身信息外,还需要存储指示其直接后继的信息。
- 表头结点: 链表中第一个结点,包含指向第一个数据匀速的指针,以及链表自身的一些信息。
- 数据结点: 链表中代表数据元素的结点,包含指向下一个数据元素的指针和信息。
- 尾结点 : 链表中最后一个数据结点,其下一个元素指针为空表表示无后继结点。
链表的种类
- 传统链表
- 非传统链表(linux内核链表)
单链表的设计
定义一个结构体指针用来存储指针与指针之间的关系:
typedef struct _tag_LinkListNode{ struct _tag_LinkListNode *next;}LinkListNode;
定义一个头结点用来存储链表:
typedef struct _tag_LinkList{ LinkListNode *header; int length;}TLinkList;
数据元素定义实例:
struct Value{ LinkListNode node; int v; };
单向链表的重要算法
- 单向链表的插入算法
- 插入前
- 插入后
- 插入前
- 单向链表的删除算法
- 删除前
- 删除后
- 删除前
单向链表的优缺点
- 优点:
- 无需一次性定制链表的容量
- 插入和删除操作无需移动数据
- 缺点:
- 数据元素必须保存后继元素的位置信息
- 获取指定数据元素操作需要访问之间的元素
单向链表的实现
LinkList.h
#ifndef _LINKLIST_H_#define _LINKLIST_H_typedef void LinkList;typedef struct _tag_LinkListNode{ struct _tag_LinkListNode *next;}LinkListNode;//创建链表LinkList *LinkList_Create();//销毁链表void LinkList_Destroy(LinkList *list);//清空链表void LinkList_Clear(LinkList *list);//获取链表的长度int LinkList_Length(LinkList *list);//向链表中第pos个位置插入node节点int LinkList_Insert(LinkList *list, int pos, LinkListNode *node);//获取链表第pos个位置节点LinkListNode *LinkList_Get(LinkList *list, int pos);//删除链表第pos个位置节点LinkListNode *LinkList_Delete(LinkList *list, int pos);#endif //LinkList
- LinkList.c
#include <stdio.h>#include <stdlib.h>#include <string.h>#include "LinkList.h"typedef struct _tag_LinkList{ LinkListNode *header; int length;}TLinkList;//创建链表LinkList *LinkList_Create() { TLinkList *ret = NULL; ret = (TLinkList *)malloc(sizeof(TLinkList)); if (ret == NULL) { printf("func LinkList_Create() err\n"); return ret; } memset(ret, 0, sizeof(ret)); ret->length = 0; ret->header = NULL; return ret;}//销毁链表void LinkList_Destroy(LinkList *list){ if (list != NULL) { free(list); return ; } return ;}//清空链表void LinkList_Clear(LinkList *list){ TLinkList *tlist = NULL; if (list == NULL) { return; } tlist = (TLinkList *)list; tlist->length = 0; tlist->header= NULL; return ;}//获取链表的长度int LinkList_Length(LinkList *list){ int ret; TLinkList *tlist = NULL; if (list == NULL) { ret = -1; printf("func LinkList_Length() err: %d\n", ret); return ret; } tlist = (TLinkList *)list; return tlist->length;}//向链表中第pos个位置插入node节点int LinkList_Insert(LinkList *list, int pos, LinkListNode *node){ int ret = 0, i = 0; TLinkList *tlist = NULL; LinkListNode *Current = NULL; //①判断线性表是否合法 if (list == NULL || pos < 0 || node == NULL) { ret = -1; printf("func LinkList_Insert() (list == NULL || pos < 0 || node == NULL) err:%d\n", ret); return ret; } tlist = (TLinkList *)list; //②判断插入位置是否合法 if (pos > tlist->length) { ret = -2; printf("func LinList_Insert() (pos > tlist->length) err: %d\n", ret); return ret; } //③插入节点 Current = &(tlist->header); for (i = 0; i < pos&&(Current->next!=NULL); i++) //找到pos位置的前一个节点 { Current = Current->next; } node->next = Current->next; //用node节点连接pos位置的后一个节点 Current->next = node; //用pos位置前一个节点连接node的节点 //④线性表长度加一 tlist->length++; return ret;}//获取链表第pos个位置节点LinkListNode *LinkList_Get(LinkList *list, int pos){ int i = 0, ret = 0; TLinkList *tlist = NULL; LinkListNode *Current = NULL; //①判断线性表是否合法 if (list == NULL || pos < 0) { ret = -1; printf("func LinkList_Get() (list == NULL || pos < 0) err: %d\n", ret); return NULL; } tlist = (LinkList *)list; //②判断插入位置是否合法 if (pos > tlist->length) { ret = -2; printf("func LinkList_Get() (pos > tlist->length) err: %d\n",ret); return NULL; } //③找到第pos位的节点 Current = &(tlist->header); for (i = 0; i < pos && (Current->next != NULL); i++) { Current = Current->next; } return Current->next;}//删除链表第pos个位置节点LinkListNode *LinkList_Delete(LinkList *list, int pos){ int i = 0, ret = 0; TLinkList *tlist = NULL; LinkListNode *Current = NULL, *tmp = NULL; //线性表是否合法 if (list == NULL || pos < 0) { ret = -1; printf("func LinkList_Get() (list == NULL || pos < 0) err: %d\n",ret); return NULL; } tlist = (TLinkList *)list; //②判断插入位置是否合法 if (pos > tlist->length) { ret = -2; printf("func LinkList_Get() (pos > tlist->length) err:%d\n",ret); return NULL; } //③删除节点 Current = &(tlist->header); for (i = 0; i < pos && (Current->next != NULL); i++)//找到pos位置的前一个节点 { Current = Current->next; } tmp = Current->next; //保存pos位置节点 Current->next = tmp->next; //pos位置的前一个节点连接pos位置的后一个节点 //④线性表长度减一 tlist->length--; return tmp;}
- LinkList集成测试框架
#define _CRT_SECURE_NO_WARNINGS# include <stdio.h># include <stdlib.h># include <string.h># include "LinkList.h"typedef struct Teacher{ LinkListNode node;//(用于与其他节点产生联系) int age; char name[64];}Teacher;void main(){ int len = 0, ret = 0, i = 0; LinkList *list = NULL; Teacher t1, t2, t3, t4, t5; t1.age = 11; strcpy(t1.name, "t1"); t2.age = 22; strcpy(t2.name, "t2"); t3.age = 33; strcpy(t3.name, "t3"); t4.age = 44; strcpy(t4.name, "t4"); t5.age = 55; strcpy(t5.name, "t5"); list = LinkList_Create(); //创建链表 if (list == NULL) //判断链表是创建成功 { printf("func LinkList_Create() err:\n"); return; } ret = LinkList_Insert(list, 0, (LinkListNode *)&t1); //在插入节点 if (ret != 0) //判断节点是否成功插入 { printf("func LinkList_Insert() err: %d\n",ret); return; } ret = LinkList_Insert(list, 1, (LinkListNode *)&t2); //在插入节点 if (ret != 0) //判断节点是否成功插入 { printf("func LinkList_Insert() err: %d\n",ret); return; } ret = LinkList_Insert(list, 2, (LinkListNode *)&t3); //在插入节点 if (ret != 0) //判断节点是否成功插入 { printf("func LinkList_Insert() err: %d\n",ret); return; } ret = LinkList_Insert(list, 3, (LinkListNode *)&t4); //在插入节点 if (ret != 0) //判断节点是否成功插入 { printf("func LinkList_Insert() err: %d\n",ret); return; } ret = LinkList_Insert(list, 4, (LinkListNode *)&t5); //在插入节点 if (ret != 0) //判断节点是否成功插入 { printf("func LinkList_Insert() err: %d\n",ret); return; } len = LinkList_Length(list); //获取链表长度 printf("The length of list is:%d\n", len); for(i=0;i<LinkList_Length(list);i++) //获取链表中的所有元素 { Teacher *tmp = NULL; tmp = (Teacher *)LinkList_Get(list, i); //获取链表第i个位置的节点 if (tmp == NULL) //判断获取节点是否成功 { printf("func LinkList_Get() err\n"); return; } printf("tmp->name:%s,tmp->age:%d\n", tmp->name, tmp->age); } while (LinkList_Length(list)) //删除链表中的所有元素 { Teacher *tmp = NULL; tmp = (Teacher *)LinkList_Delete(list, 0); //删除链表第一个位置节点 if (tmp == NULL) //判断删除节点是否成功 { printf("func LinkList_Delete() err\n"); return; } printf("tmp->name:%s,tmp->age:%d\n", tmp->name, tmp->age); } len = LinkList_Length(list); //获取链表长度 printf("The length of list is:%d\n", len); LinkList_Clear(list); //清空链表 LinkList_Destroy(list); //销毁链表 return;}
阅读全文
1 0
- 线性表(List)---链式存储结构(单向链表)
- 线性表(List)---链式存储结构(双向链表)
- 链式存储结构之单向链表
- 大话数据结构四:线性表的链式存储结构(单向循环链表)
- 大话数据结构四:线性表的链式存储结构(单向循环链表)
- 二.单向链式存储线性表
- 线性表-链式存储结构
- 链式存储结构线性表
- 【数据结构】单向线性链式物理结构list
- ※数据结构※→☆线性表结构(list)☆============单向链表 链式存储结构(list single)(二)
- ※数据结构※→☆线性表结构(list)☆============单向循环链表 链式存储结构(list circular single)(四)
- 数据结构----纯C语言实现线性表的单向链式存储结构
- 线性表(List)---栈的链式存储
- 线性表(List)---队列的链式存储
- 线性表的链式存储结构
- 线性表 -- 链式存储结构(单链表)
- 链式存储结构的线性表
- 线性表的链式存储结构
- vim ctags
- C++程序员学Java系列之九:流程控制语句if,else
- Animation 滑动切换界面
- 计算器的实现
- android的转盘
- 线性表(List)---链式存储结构(单向链表)
- C++程序员学Java系列之十:Java中的循环while,for,do while,猜数字案例
- No tests found with test runner JUnit4
- Golang 优化之路——临时对象池
- jmeter
- hive------select语法介绍
- LeetCode 69. Sqrt(x)
- Apriori的Python实现
- java基础入门学习