数据结构_静态链表(C语言)
数据结构总目录
本章目录
- (一)静态链表图文解析
- (二)静态链表代码解析
- 1. 基本操作
- 1.1 存储结构
- 1.2 初始化
- 1.3 插入数据
- 1.4 删除数据
- 1.5 修改数据
- 2. 源代码及测试
- 2.1 源代码
- 2.2 测试结果
(一)静态链表图文解析
静态链表结构
- 静态链表的结构实际上就是一个数组,静态链表的数组中,每一个元素代表一个结点,结点同样和链表一样包括数据域和指针域
- 只是在静态链表中的指针域不再是指针指向下一个结点的地址,而是用于存储下一个结点的数组下标,这样同样可以实现结点之间的连接关系
图示
在静态链表中
- 指针域大于0,则代表下一个结点的数组下标
- 指针域等于-1,则代表下一个结点为空
- 指针域等于-2,则代表该结点尚未被使用
(二)静态链表代码解析
1. 基本操作
1.1 存储结构
#define MaxSize 10 //最大链表长度typedef char DataType;
typedef struct LNode
{DataType data; //数据域int next; //指针域
}StaticList;
1.2 初始化
void InitList(StaticList **L)
{// 为静态链表分配空间(*L) = (StaticList *)malloc(MaxSize * sizeof(StaticList));// 初始化头结点StaticList *s = *L;s[0].data = '\0';s[0].next = -1;// 初始化链表int i;for (i = 1; i < MaxSize; i++){s[i].data = '\0';s[i].next = -2;}printf("已初始化链表\n");
}
1.3 插入数据
头部插入
void HeadInsert(StaticList *L)
{if (L){DataType x;printf("请输入插入的数据:");fflush(stdin);scanf("%c", &x);// 获取新结点的下标位置int free_node = GetFreeNodeIndex(L);if (free_node > 0){// 设置新结点的数据L[free_node].data = x;// 新结点指向链表的第一个结点L[free_node].next = L[0].next;// 头结点指向新结点,使得新结点成为链表的第一个结点L[0].next = free_node;printf("插入成功!\n");}else{printf("插入失败! 链表空间已满!\n");} }else{printf("插入失败! 链表已销毁!\n");}
}
尾部插入
void TailInsert(StaticList *L)
{if (L){int i;DataType x;printf("请输入插入的数据:");fflush(stdin);scanf("%c", &x);int free_node = GetFreeNodeIndex(L);if (free_node > 0){int tail_index = 0;// 查找尾结点下标while (L[tail_index].next > 0){tail_index = L[tail_index].next;}// 设置新结点数据L[free_node].data = x;// 新结点指针域设置为空L[free_node].next = -1;//尾结点指向新结点,使得新结点成为链表的最后一个结点L[tail_index].next = free_node;printf("插入成功!\n");}else{printf("插入失败! 链表空间已满\n");}}else{printf("插入失败! 链表已销毁!\n");}
}
按位置插入
void LocateInsert(StaticList *L)
{if (L){int i, k;DataType x;printf("请输入插入的数据和插入位置:");scanf("%d %c", &k, &x);int free_node = GetFreeNodeIndex(L);if (k > 0 && free_node > 0){int insert_index = 0;// 查找链表中第(k-1)个结点while((--k) && L[insert_index].next > 0){ insert_index = L[insert_index].next;}// 插入新结点if (k == 0){// 设置新结点数据L[free_node].data = x;// 新结点指向第k个结点下标L[free_node].next = L[insert_index].next;// 第(k-1)个结点指向新结点L[insert_index].next = free_node;printf("插入成功!\n");}else{printf("插入失败! 插入位置不合法!\n");}}else{printf("插入失败! 插入位置不合法/链表空间已满!\n");}}else{printf("插入失败! 链表已销毁!\n");}
}
1.4 删除数据
头部删除
void HeadDelete(StaticList *L)
{if (L){if (L[0].next > 0){int first_index;// 获取第一个结点first_index = L[0].next;// 头结点指向第二个结点L[0].next = L[first_index].next;// 初始化第一个结点L[first_index].data = '\0';L[first_index].next = -2;printf("删除成功!\n");}else{printf("删除失败! 链表为空!\n");}}else{printf("删除失败! 链表已销毁!\n");}
}
尾部删除
// 尾部删除
void TailDelete(StaticList *L)
{if (L){if (L[0].next > 0){int i = 0, j = 0;// 查询倒数第一个结点(i)和倒数第二个结点(j)while (L[i].next > 0){j = i;i = L[i].next;}// 倒数第二个结点指向-1L[j].next = -1;// 初始化最后一个结点L[i].data = '\0';L[i].next = -2;printf("删除成功!\n");}else{printf("插入失败! 链表为空!\n");}}else{printf("插入失败! 链表已销毁!\n");}
}
按位置删除
// 按位置删除
void LocateDelete(StaticList *L)
{if (L){int k;printf("请输入删除的数据位置:");scanf("%d", &k);if (k > 0 && L[0].next > 0){int i = 0, j = 0;// 查询第(j = k-1)个结点和第(i = k)个结点while ((k--) && L[i].next > 0){j = i;i = L[i].next;}if (k < 0){// 第(k-1)个结点指向第(k+1)个结点L[j].next = L[i].next;// 初始化第k个结点L[i].data = '\0';L[i].next = -2;printf("删除成功!\n");}else{printf("删除失败! 删除位置不合法!\n");} }else{printf("删除失败! 链表为空!\n");}}else{printf("删除失败! 链表已销毁!\n");}
}
1.5 修改数据
// 修改链表
void ListModify(StaticList *L)
{if (L){int k;DataType x;printf("请输入需要修改的位置和修改后的数据:");scanf("%d %c", &k, &x);if (k > 0){ int index = 0;// 查询第i个结点位置while ((k--) && L[index].next > 0){index = L[index].next;} if (k < 0){L[index].data = x;printf("修改成功!\n");}else{printf("修改失败! 修改位置不合法!\n");}}else{printf("修改失败! 修改位置不合法!\n");}}else{printf("链表已销毁!\n");}
}
2. 源代码及测试
2.1 源代码
#include<stdio.h>
#include<stdlib.h>#define MaxSize 10typedef char DataType;
typedef struct LNode
{DataType data;int next;
}StaticList;void InitList(StaticList **L)
{// 为静态链表分配空间(*L) = (StaticList *)malloc(MaxSize * sizeof(StaticList));// 初始化StaticList *s = *L;s[0].data = '\0';s[0].next = -1;int i;for (i = 1; i < MaxSize; i++){s[i].data = '\0';s[i].next = -2;}printf("已初始化链表\n");
}// 查找空闲结点位置的下标
int GetFreeNodeIndex(StaticList *L)
{int i;for (i = 1; i < MaxSize; i++){ if (L[i].next == -2){return i;}}return 0;
}// 头部插入
void HeadInsert(StaticList *L)
{if (L){DataType x;printf("请输入插入的数据:");fflush(stdin);scanf("%c", &x);// 获取新结点的下标位置int free_node = GetFreeNodeIndex(L);if (free_node > 0){// 设置新结点的数据L[free_node].data = x;// 新结点指向链表的第一个结点L[free_node].next = L[0].next;// 头结点指向新结点,使得新结点成为链表的第一个结点L[0].next = free_node;printf("插入成功!\n");}else{printf("插入失败! 链表空间已满!\n");} }else{printf("插入失败! 链表已销毁!\n");}
}// 尾部插入
void TailInsert(StaticList *L)
{if (L){int i;DataType x;printf("请输入插入的数据:");fflush(stdin);scanf("%c", &x);int free_node = GetFreeNodeIndex(L);if (free_node > 0){int tail_index = 0;// 查找尾结点下标while (L[tail_index].next > 0){tail_index = L[tail_index].next;}// 设置新结点数据L[free_node].data = x;// 新结点指针域设置为空L[free_node].next = -1;//尾结点指向新结点,使得新结点成为链表的最后一个结点L[tail_index].next = free_node;printf("插入成功!\n");}else{printf("插入失败! 链表空间已满\n");}}else{printf("插入失败! 链表已销毁!\n");}
}// 按位置插入
void LocateInsert(StaticList *L)
{if (L){int i, k;DataType x;printf("请输入插入的数据和插入位置:");scanf("%d %c", &k, &x);int free_node = GetFreeNodeIndex(L);if (k > 0 && free_node > 0){int insert_index = 0;// 查找链表中第(k-1)个结点while((--k) && L[insert_index].next > 0){ insert_index = L[insert_index].next;}// 插入新结点if (k == 0){// 设置新结点数据L[free_node].data = x;// 新结点指向第k个结点下标L[free_node].next = L[insert_index].next;// 第(k-1)个结点指向新结点L[insert_index].next = free_node;printf("插入成功!\n");}else{printf("插入失败! 插入位置不合法!\n");}}else{printf("插入失败! 插入位置不合法/链表空间已满!\n");}}else{printf("插入失败! 链表已销毁!\n");}
}// 头部删除
void HeadDelete(StaticList *L)
{if (L){if (L[0].next > 0){int first_index;// 获取第一个结点first_index = L[0].next;// 头结点指向第二个结点L[0].next = L[first_index].next;// 初始化第一个结点L[first_index].data = '\0';L[first_index].next = -2;printf("删除成功!\n");}else{printf("删除失败! 链表为空!\n");}}else{printf("删除失败! 链表已销毁!\n");}
}// 尾部删除
void TailDelete(StaticList *L)
{if (L){if (L[0].next > 0){int i = 0, j = 0;// 查询倒数第一个结点(i)和倒数第二个结点(j)while (L[i].next > 0){j = i;i = L[i].next;}// 倒数第二个结点指向-1L[j].next = -1;// 初始化最后一个结点L[i].data = '\0';L[i].next = -2;printf("删除成功!\n");}else{printf("插入失败! 链表为空!\n");}}else{printf("插入失败! 链表已销毁!\n");}
}// 按位置删除
void LocateDelete(StaticList *L)
{if (L){int k;printf("请输入删除的数据位置:");scanf("%d", &k);if (k > 0 && L[0].next > 0){int i = 0, j = 0;// 查询第(j = k-1)个结点和第(i = k)个结点while ((k--) && L[i].next > 0){j = i;i = L[i].next;}if (k < 0){// 第(k-1)个结点指向第(k+1)个结点L[j].next = L[i].next;// 初始化第k个结点L[i].data = '\0';L[i].next = -2;printf("删除成功!\n");}else{printf("删除失败! 删除位置不合法!\n");} }else{printf("删除失败! 链表为空!\n");}}else{printf("删除失败! 链表已销毁!\n");}
}// 修改链表
void ListModify(StaticList *L)
{if (L){int k;DataType x;printf("请输入需要修改的位置和修改后的数据:");scanf("%d %c", &k, &x);if (k > 0){ int index = 0;// 查询第i个结点位置while ((k--) && L[index].next > 0){index = L[index].next;} if (k < 0){L[index].data = x;printf("修改成功!\n");}else{printf("修改失败! 修改位置不合法!\n");}}else{printf("修改失败! 修改位置不合法!\n");}}else{printf("链表已销毁!\n");}
}// 遍历链表
void DisplayList(StaticList *L)
{if (L){if (L[0].next > 0){int index = L[0].next;while(index > 0){printf("%c->", L[index].data);index = L[index].next;}printf("null\n");}else{printf("链表为空!\n");} }else{printf("遍历失败! 链表已销毁!\n");}
}// 求链表长度
void ListLength(StaticList *L)
{if (L){int index = 0, length = 0;while (L[index].next > 0){length++;index = L[index].next;}printf("链表长度length = %d\n", length);}else{printf("链表已销毁!\n");}
}// 判断链表是否为空
void ListEmpty(StaticList *L)
{if (L){if (L[0].next > 0){printf("链表非空!\n");}else{printf("链表为空!\n");}}else{printf("链表已销毁!\n");}
}// 清空链表
void ClearList(StaticList *L)
{if (L){if (L[0].next > 0){int i = L[0].next, j = L[0].next;// 依次清除结点while (i > 0){// j:用于暂存下一个结点j = L[i].next;// 初始化结点iL[i].next = -2;// i:移动到下一个结点i = j;}L[0].next = -1;printf("链表已清空!\n");}else{printf("链表为空!\n");} }else{printf("链表已销毁!\n");}
}// 销毁链表
void DestroyList(StaticList **L)
{free(*L);(*L) = NULL;printf("链表已销毁!\n");
}// 打印静态链表数组
void DisplayArr(StaticList *L)
{if (L){ int i;printf("***************************\n");printf("下标:\t");for (i = 0; i < MaxSize; i++){printf("%d\t", i); }printf("\n数据域:\t");for (i = 0; i < MaxSize; i++){if (L[i].data){printf("%c\t", L[i].data);}else{printf("-\t");}}printf("\n指针域:\t");for (i = 0; i < MaxSize; i++){printf("%d\t", L[i].next);}printf("\n***************************\n");}else{printf("链表已销毁!\n");}
}int main()
{printf("*********************************\n");printf("其他 | 0:退出\t1:初始化\n");printf("插入 | 2:头插\t3:尾插\t4:按位插\n");printf("删除 | 5:头删\t6:尾删\t7:按位删\n");printf("查询 | 8:修改\t9:遍历\t10:求表长\n");printf("其他 | 11:表空\t12:清空\t13:销毁\n");printf("测试 | 14:打印静态链表数组\n");printf("*********************************\n");int k;StaticList *L;InitList(&L);while (1){printf("请输入操作序号:");scanf("%d", &k);if (!k){break;}switch (k){case 1:InitList(&L); break;// 插入case 2:HeadInsert(L); break;case 3:TailInsert(L); break;case 4:LocateInsert(L); break;// 删除case 5:HeadDelete(L); break;case 6:TailDelete(L); break;case 7:LocateDelete(L); break;// 查询case 8:ListModify(L); break;case 9:DisplayList(L); break;case 10:ListLength(L); break;// 其他case 11:ListEmpty(L); break;case 12:ClearList(L); break;case 13:DestroyList(&L);break;case 14:DisplayArr(L); break;default:break;}printf("\n");}system("pause");return 0;
}
2.2 测试结果
数据结构_静态链表(C语言)相关推荐
- c语言将一个已知头结点的单链表逆序_C语言实现常用数据结构:静态链表数组实现(第5篇)...
「今天是学习C语言第 148 天」 纸上学来终觉浅,绝知此事要躬行.-- 陆游「冬夜读书示子聿」 # 静态链表 使用数组实现,利用数组下标代替指针,从而实现数据结点之间的先后关系.实现要点: 1.数组 ...
- java静态链表_静态链表及其创建(C语言实现)
<顺序表和链表优缺点>一节,我们了解了两种存储结构各自的特点,那么,是否存在一种存储结构,可以融合顺序表和链表各自的优点,从而既能快速访问元素,又能快速增加或删除数据元素. 静态链表,也是 ...
- 数据结构:静态链表实现树的同构
写在最前面 按照课程讲解的思路来写,逻辑关系能够理解清楚了,但是实际运行起来实在是有问题,虽然在PTA上能够通过.但是我自己看不出问题来,并且,看了一遍又一遍仍然看不出来!(可能自己太笨..)这就说明 ...
- 数据结构 2-3-4 静态链表
一.概念 静态链表相当于混合了数组和链表,单独的链表,使用next指针指向内存空间中下一个节点的位置来实现连接的,而数组中是用相对位置来实现,将二者混合,保留指向下一个的指针,但这个指针不是指针,而是 ...
- 数据结构_线索二叉树(C语言)
数据结构总目录 线索二叉树 1. 结构解析 线索二叉树,是对链式二叉树中的空指针的再次利用,在一般的链式二叉树中,叶子结点都存在左右空指针,所以为了不浪费这些空指针,于是就有了线索二叉树. 线索二叉树 ...
- 数据结构_排序二叉树(C语言)
数据结构总目录 排序二叉树 1. 结构解析 排序二叉树的结构规则很简单,只遵循一个基本规则: 那就是在二叉树中,选择任意根结点,其左子树都比根节点小,右子树都比根节点大. 排序二叉树结构图 观察如下二 ...
- 数据结构_分块查找(C语言)
数据结构总目录 分块查找 分块查找又称索引顺序查找,这是一种性能介于顺序查找和折半查找之间的一种查找方法,也是顺序查找和折半查找的组合查找结合查找方法. 1. 图文解析 在分块查找中 (1)需要建立一 ...
- Scratch 与C语言实现数据结构静态链表的建立及操作
Scratch 实现数据结构静态链表的建立及操作 scratch操作 Scratch 实现数据结构静态链表的建立及操作 数据结构 初始化静态链表 添加数据代码 删除数据 回收空闲节点操作代码 计算静态 ...
- 线性表详解(静态链表、单链表、双向链表、循环链表)
目录 申明 1. 线性表的定义 2. 线性表的抽象数据类型 3. 线性表的顺序存储结构 3. 1 顺序存储定义 3. 2 顺序存储方式 3. 3 数据长度与线性表长度区别 3. 4 地址计算方法 4. ...
- java静态链表_数据结构笔记:静态链表(C语言)
void CreateList(StaticLinkList *P)//创建一个静态链表 { int i; for(i=0;i此时并没有已占用空间,所以第一个节点中的指针(cur)的值为1,也就是说空 ...
最新文章
- Django MTV模型思想
- 流程的python-流畅的Python
- 160个Crackme010
- HDFS High Availability体系介绍(Using the Quorum Journal Manager)
- 清华大学:全面如期开课,履行社会责任!
- MongoDB 定位 oplog 必须全表扫描吗?
- xposed hook 静态函数_浅谈 Xposed 新概念【模块作用域】
- SolidEdge 如何绘制局部视图 局部放大图
- mysql设置最大查询时间_mysql如何限制sql查询时间
- 随想录(搭建自己嵌入式项目的编译系统)
- java中多态案例工厂类,Java中构造器内部的多态方法的行为实例分析
- spring事务失效二:业务代码捕获异常
- 柯尼卡美能达一体机 扫描文件,不是全彩的,就首页和尾页是彩色,中间黑白
- MCTS人工智能围棋
- html手机端最小字体,移动端最小字体限制测试
- 实时分析:Flume+Kafka+SparkStreaming商品评分排行榜
- 讯时网关路由规则小结
- “decompose“没有适用于“ts“目标对象的方法
- MacBook电池使用策略
- ifconfig 使用