数据结构04:静态链表
摘要:事实上,静态链表可以让我们更好地理解空间分配机制。由我们对一片空间来进行分配管理,如我们在链表中就用到了int *used来检查这篇空间是否被占用,模拟操作系统是如何判断一片空间是否被占用。
再者,我们对于静态链表的地址模拟选用了整型int next,用next来代表下一个访问数据的下标,实际上下标其实对于数组来说就是他的地址,我们有了地址就可以访问到对应地址存放的数据。这个东西对应的就是单链表的next,只不过单链表的next是操作系统分配给我们的真实地址,我们的目的就是模拟。
其实对于后续的插入,删除等基本操作,就和我们单链表差不太多。只是多了一步我们需要自己来确定是否有空间来进行操作,并且分配空间。
话不多说,我们来看一看静态链表到底是如何运转的。
一.代码块
1)创建链表
#define DEFAULT_SIZE 5 //与单链表不同,该链表我们所能控制的空间大小是一开始就确定的。 typedef struct StaticLinkedNode
{char data; //数据域 int next; //这个是用来存放数组下标,即下一个数据地址的(我们用-1来模拟NULL)
} *NodePtr;typedef struct StaticLinkedList
{NodePtr nodes;int* used; //我们用used来确定空间是否被占用,占用赋1,未占用赋0;
} *ListPtr;
2)初始化链表
ListPtr initLinkedList()
{ListPtr tempPtr = (ListPtr)malloc(sizeof(struct StaticLinkedList));//所有的空间都提前申请好了 tempPtr->nodes = (NodePtr)malloc(sizeof(struct StaticLinkedNode) * DEFAULT_SIZE);tempPtr->used = (int*)malloc(sizeof(int) * DEFAULT_SIZE);// 第一个结点数据域不能存放东西,但是他要占用我们申请的一个空间,所以我们实际能用的空间要比申请的少一个 tempPtr->nodes[0].data = '\0';tempPtr->nodes[0].next = -1;//这里初始化只有第一个结点是被占用的,我们给used赋值。 tempPtr->used[0] = 1;int i; for (i = 1; i < DEFAULT_SIZE; i ++){tempPtr->used[i] = 0;}return tempPtr;
}
3)打印链表
void printList(ListPtr paraListPtr)
{//这里如果从第0个开始打印,就把头结点的'\0'也打印出来了 int p = paraListPtr->nodes[0].next;//这样写直接从头结点后面第一个数据开始打印 while (p != -1) {printf("%c", paraListPtr->nodes[p].data);p = paraListPtr->nodes[p].next;}printf("\r\n");}
4)指定位置插入元素
void insertElement(ListPtr paraListPtr, char paraChar, int paraPosition){int p, q, i;//第一步仍然是帮助p找到他的位置 p = 0;//就相当于单链表里面的 p = paraHeader; for (i = 0; i < paraPosition; i ++) {p = paraListPtr->nodes[p].next;if (p == -1) {printf("The position %d is beyond the scope of the list.\r\n", paraPosition);return;}}//第二步:找到正确的位置后,再看有没有空间来存放数据 //这一步就相当于malloc申请空间,只不过现在我们是操作系统,我们自己来分配空间 for (i = 1; i < DEFAULT_SIZE; i ++){if (paraListPtr->used[i] == 0){printf("Space at %d allocated.\r\n", i);paraListPtr->used[i] = 1;q = i;break;}}if (i == DEFAULT_SIZE){printf("No space.\r\n");return;}paraListPtr->nodes[q].data = paraChar;//这里的操作其实就是和单链表一样的 printf("linking\r\n");paraListPtr->nodes[q].next = paraListPtr->nodes[p].next;paraListPtr->nodes[p].next = q;
}
5)删除指定元素
void deleteElement(ListPtr paraListPtr, char paraChar)
{int p, q;p = 0;/*有了插入元素的基础,我们不难发现,你把 paraListPtr->nodes[p].next换成 p->next然后就会发现所有的操作和单链表一模一样*/ //找到p的位置 while ((paraListPtr->nodes[p].next != -1) && (paraListPtr->nodes[paraListPtr->nodes[p].next].data != paraChar)){p = paraListPtr->nodes[p].next;}if (paraListPtr->nodes[p].next == -1) {printf("Cannot delete %c\r\n", paraChar);return;}q = paraListPtr->nodes[p].next;paraListPtr->nodes[p].next = paraListPtr->nodes[paraListPtr->nodes[p].next].next;// 这一步就相当于free(q) paraListPtr->used[q] = 0;
}
5)测试代码
void appendInsertDeleteTest()
{ListPtr tempList = initLinkedList();printList(tempList);// 像老师这样每一次都在最后一个插入不但测试到了两个边界,还测试到了没有空间的情况.insertElement(tempList, 'H', 0);insertElement(tempList, 'e', 1);insertElement(tempList, 'l', 2);insertElement(tempList, 'l', 3);insertElement(tempList, 'o', 4);printList(tempList);//删除测试 printf("Deleting 'e'.\r\n");deleteElement(tempList, 'e');printf("Deleting 'a'.\r\n");deleteElement(tempList, 'a');printf("Deleting 'o'.\r\n");deleteElement(tempList, 'o');printList(tempList);insertElement(tempList, 'x', 1);printList(tempList);
}
二.图示部分
我个人觉得,静态链表的插入删除操作完全和单链表一样。难在你要把我们用整形next指向下标也等于指向了地址这个操作理解,还有一点就是多了一个空间检测以及分配。
这两点理解到了后,对于其插入和删除的图示其实是完全等同于单链表的,如有需要,可以去我之前单链表和或者双链表文章里面查看。
三.全部代码
#include <stdio.h>
#include <malloc.h>#define DEFAULT_SIZE 5 //与单链表不同,该链表我们所能控制的空间大小是一开始就确定的。 typedef struct StaticLinkedNode
{char data; //数据域 int next; //这个是用来存放数组下标,即下一个数据地址的(我们用-1来模拟NULL)
} *NodePtr;typedef struct StaticLinkedList
{NodePtr nodes;int* used; //我们用used来确定空间是否被占用,占用赋1,未占用赋0;
} *ListPtr;/*** Initialize the list with a header.* @return The pointer to the header.*/
ListPtr initLinkedList()
{ListPtr tempPtr = (ListPtr)malloc(sizeof(struct StaticLinkedList));//所有的空间都提前申请好了 tempPtr->nodes = (NodePtr)malloc(sizeof(struct StaticLinkedNode) * DEFAULT_SIZE);tempPtr->used = (int*)malloc(sizeof(int) * DEFAULT_SIZE);// 第一个结点数据域不能存放东西,但是他要占用我们申请的一个空间,所以我们实际能用的空间要比申请的少一个 tempPtr->nodes[0].data = '\0';tempPtr->nodes[0].next = -1;//这里初始化只有第一个结点是被占用的,我们给used赋值。 tempPtr->used[0] = 1;int i; for (i = 1; i < DEFAULT_SIZE; i ++){tempPtr->used[i] = 0;}return tempPtr;
}void printList(ListPtr paraListPtr)
{//这里如果从第0个开始打印,就把头结点的'\0'也打印出来了 int p = paraListPtr->nodes[0].next;//这样直接从头结点后面第一个数据开始打印 while (p != -1) {printf("%c", paraListPtr->nodes[p].data);p = paraListPtr->nodes[p].next;}printf("\r\n");}void insertElement(ListPtr paraListPtr, char paraChar, int paraPosition){int p, q, i;//第一步仍然是帮助p找到他的位置 p = 0;//就相当于单链表里面的 p = paraHeader; for (i = 0; i < paraPosition; i ++) {p = paraListPtr->nodes[p].next;if (p == -1) {printf("The position %d is beyond the scope of the list.\r\n", paraPosition);return;}}//第二步:找到正确的位置后,再看有没有空间来存放数据 //这一步就相当于malloc申请空间,只不过现在我们是操作系统,我们自己来分配空间 for (i = 1; i < DEFAULT_SIZE; i ++){if (paraListPtr->used[i] == 0){printf("Space at %d allocated.\r\n", i);paraListPtr->used[i] = 1;q = i;break;}}if (i == DEFAULT_SIZE){printf("No space.\r\n");return;}paraListPtr->nodes[q].data = paraChar;//这里的操作其实就是和单链表一样的 printf("linking\r\n");paraListPtr->nodes[q].next = paraListPtr->nodes[p].next;paraListPtr->nodes[p].next = q;
}void deleteElement(ListPtr paraListPtr, char paraChar)
{int p, q;p = 0;/*有了插入元素的基础,我们不难发现,你把 paraListPtr->nodes[p].next换成 p->next然后就会发现所有的操作和单链表一模一样*/ //找到p的位置 while ((paraListPtr->nodes[p].next != -1) && (paraListPtr->nodes[paraListPtr->nodes[p].next].data != paraChar)){p = paraListPtr->nodes[p].next;}if (paraListPtr->nodes[p].next == -1) {printf("Cannot delete %c\r\n", paraChar);return;}q = paraListPtr->nodes[p].next;paraListPtr->nodes[p].next = paraListPtr->nodes[paraListPtr->nodes[p].next].next;// 这一步就相当于free(q) paraListPtr->used[q] = 0;
}/*** Unit test.*/
void appendInsertDeleteTest()
{ListPtr tempList = initLinkedList();printList(tempList);// 像老师这样每一次都在最后一个插入不但测试到了两个边界,还测试到了没有空间的情况.insertElement(tempList, 'H', 0);insertElement(tempList, 'e', 1);insertElement(tempList, 'l', 2);insertElement(tempList, 'l', 3);insertElement(tempList, 'o', 4);printList(tempList);//删除测试 printf("Deleting 'e'.\r\n");deleteElement(tempList, 'e');printf("Deleting 'a'.\r\n");deleteElement(tempList, 'a');printf("Deleting 'o'.\r\n");deleteElement(tempList, 'o');printList(tempList);insertElement(tempList, 'x', 1);printList(tempList);
}void main()
{appendInsertDeleteTest();
}
四.运行结果
数据结构04:静态链表相关推荐
- c语言将一个已知头结点的单链表逆序_C语言实现常用数据结构:静态链表数组实现(第5篇)...
「今天是学习C语言第 148 天」 纸上学来终觉浅,绝知此事要躬行.-- 陆游「冬夜读书示子聿」 # 静态链表 使用数组实现,利用数组下标代替指针,从而实现数据结点之间的先后关系.实现要点: 1.数组 ...
- 数据结构:静态链表实现树的同构
写在最前面 按照课程讲解的思路来写,逻辑关系能够理解清楚了,但是实际运行起来实在是有问题,虽然在PTA上能够通过.但是我自己看不出问题来,并且,看了一遍又一遍仍然看不出来!(可能自己太笨..)这就说明 ...
- 数据结构 2-3-4 静态链表
一.概念 静态链表相当于混合了数组和链表,单独的链表,使用next指针指向内存空间中下一个节点的位置来实现连接的,而数组中是用相对位置来实现,将二者混合,保留指向下一个的指针,但这个指针不是指针,而是 ...
- Scratch 与C语言实现数据结构静态链表的建立及操作
Scratch 实现数据结构静态链表的建立及操作 scratch操作 Scratch 实现数据结构静态链表的建立及操作 数据结构 初始化静态链表 添加数据代码 删除数据 回收空闲节点操作代码 计算静态 ...
- c语言 静态链表插入排序,数据结构C语言版 表插入排序
西门豹治邺奇计 数据结构C语言版 表插入排序.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情./* 数据结构C语言版 表插入排序 算法10.3 P267-P2 ...
- 【数据结构】线性表的链式表示-循环单链表、循环双链表、静态链表
循环单链表 从任何一个结点出发都能访问到链表的每一个元素 判空条件不是头节点的后继指针是否为空,而是它是否等于头指针 有时对单链表常做的操作实在表头和表尾进行的,此时可对循环单链表不设头指针而仅设尾指 ...
- c语言 静态链表插入排序,数据结构 - 表插入排序 具体解释 及 代码(C++)
表插入排序 具体解释 及 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24323125 表插入排序(List I ...
- 静态链表(C++实现)——基于数据结构(沈俊版)(初学者食用)
静态链表(C++实现)--基于数据结构(沈俊版) 初学数据结构,不喜勿喷.欢迎大佬们指正! 静态链表是利用数组来模拟存储空间来实现链表的,如果为数组中每一个元素附加一个链接指针(数组下标),就形成静态 ...
- 【C语言X数据结构】用静态链表实现的多项式计算器,加减乘除求导求值,输入输出样样在行!(完整代码+注释)
目录 实验要求 完整代码 逻辑设计 哈喽各位好,我是李博轩,一个刚转到计算机的大二学生.这个标题是随手打上去的,感觉还蛮顺口,就这样了. 这个学期在学[数据结构与算法],而这是我面对的第一个实验题.因 ...
最新文章
- day44前端开发1之html基础
- 用asp.net实现的把本文推荐给好友功能
- 大揭秘:程序员工作也可以成为享受!
- python3 多进程库 multiprocessing 使用简介
- leetcode算法题--解码方法★
- Linux的cp -a与cp -p
- wordpress mysql 挂了_大神们,诊断一下,wampserver的mysql老是挂掉!
- php框架中uri路由机制,URI 路由 — CodeIgniter 3.1.5 中文手册|用户手册|用户指南|中文文档...
- 怎么判断一个字符串的最长回文子串是否在头尾_最长回文字串/子序列问题(leetcode5,9,519)
- 互联网裁员屡见不鲜,但有时互联网的裁员却不太体面
- 将系统常用程序一次性的都安装到位
- mysql关联查询关键字_MySQL数据高级查询之连接查询、联合查询、子查询
- KITTI数据集下载
- Layabox创始人谢成鸿:我有一个坚持!
- python网课什么平台好-这些AI课网课最具人气!不仅免费、系统,还附带链接 | 资源...
- 为什么中国程序员非要用英文编程,而不用汉字编程
- 高中会考计算机试题及答案,高中计算机会考试题及答案
- 领导的沉默,背后到底隐藏着什么?
- 衣服裤子染色了怎么办
- 联想笔记本昭阳K22-80重装win7纪要