摘要:事实上,静态链表可以让我们更好地理解空间分配机制。由我们对一片空间来进行分配管理,如我们在链表中就用到了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:静态链表相关推荐

  1. c语言将一个已知头结点的单链表逆序_C语言实现常用数据结构:静态链表数组实现(第5篇)...

    「今天是学习C语言第 148 天」 纸上学来终觉浅,绝知此事要躬行.-- 陆游「冬夜读书示子聿」 # 静态链表 使用数组实现,利用数组下标代替指针,从而实现数据结点之间的先后关系.实现要点: 1.数组 ...

  2. 数据结构:静态链表实现树的同构

    写在最前面 按照课程讲解的思路来写,逻辑关系能够理解清楚了,但是实际运行起来实在是有问题,虽然在PTA上能够通过.但是我自己看不出问题来,并且,看了一遍又一遍仍然看不出来!(可能自己太笨..)这就说明 ...

  3. 数据结构 2-3-4 静态链表

    一.概念 静态链表相当于混合了数组和链表,单独的链表,使用next指针指向内存空间中下一个节点的位置来实现连接的,而数组中是用相对位置来实现,将二者混合,保留指向下一个的指针,但这个指针不是指针,而是 ...

  4. Scratch 与C语言实现数据结构静态链表的建立及操作

    Scratch 实现数据结构静态链表的建立及操作 scratch操作 Scratch 实现数据结构静态链表的建立及操作 数据结构 初始化静态链表 添加数据代码 删除数据 回收空闲节点操作代码 计算静态 ...

  5. c语言 静态链表插入排序,数据结构C语言版 表插入排序

    西门豹治邺奇计 数据结构C语言版 表插入排序.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情./* 数据结构C语言版 表插入排序 算法10.3 P267-P2 ...

  6. 【数据结构】线性表的链式表示-循环单链表、循环双链表、静态链表

    循环单链表 从任何一个结点出发都能访问到链表的每一个元素 判空条件不是头节点的后继指针是否为空,而是它是否等于头指针 有时对单链表常做的操作实在表头和表尾进行的,此时可对循环单链表不设头指针而仅设尾指 ...

  7. c语言 静态链表插入排序,数据结构 - 表插入排序 具体解释 及 代码(C++)

    表插入排序 具体解释 及 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24323125 表插入排序(List I ...

  8. 静态链表(C++实现)——基于数据结构(沈俊版)(初学者食用)

    静态链表(C++实现)--基于数据结构(沈俊版) 初学数据结构,不喜勿喷.欢迎大佬们指正! 静态链表是利用数组来模拟存储空间来实现链表的,如果为数组中每一个元素附加一个链接指针(数组下标),就形成静态 ...

  9. 【C语言X数据结构】用静态链表实现的多项式计算器,加减乘除求导求值,输入输出样样在行!(完整代码+注释)

    目录 实验要求 完整代码 逻辑设计 哈喽各位好,我是李博轩,一个刚转到计算机的大二学生.这个标题是随手打上去的,感觉还蛮顺口,就这样了. 这个学期在学[数据结构与算法],而这是我面对的第一个实验题.因 ...

最新文章

  1. day44前端开发1之html基础
  2. 用asp.net实现的把本文推荐给好友功能
  3. 大揭秘:程序员工作也可以成为享受!
  4. python3 多进程库 multiprocessing 使用简介
  5. leetcode算法题--解码方法★
  6. Linux的cp -a与cp -p
  7. wordpress mysql 挂了_大神们,诊断一下,wampserver的mysql老是挂掉!
  8. php框架中uri路由机制,URI 路由 — CodeIgniter 3.1.5 中文手册|用户手册|用户指南|中文文档...
  9. 怎么判断一个字符串的最长回文子串是否在头尾_最长回文字串/子序列问题(leetcode5,9,519)
  10. 互联网裁员屡见不鲜,但有时互联网的裁员却不太体面
  11. 将系统常用程序一次性的都安装到位
  12. mysql关联查询关键字_MySQL数据高级查询之连接查询、联合查询、子查询
  13. KITTI数据集下载
  14. Layabox创始人谢成鸿:我有一个坚持!
  15. python网课什么平台好-这些AI课网课最具人气!不仅免费、系统,还附带链接 | 资源...
  16. 为什么中国程序员非要用英文编程,而不用汉字编程
  17. 高中会考计算机试题及答案,高中计算机会考试题及答案
  18. 领导的沉默,背后到底隐藏着什么?
  19. 衣服裤子染色了怎么办
  20. 联想笔记本昭阳K22-80重装win7纪要

热门文章

  1. 群脉冲(EFT)异常整改记录
  2. 项目总结(VideoStream网页播放视频)
  3. 羊皮卷的故事-第十三章-羊皮卷之六
  4. 在Oracle中添加的中文变成靠靠靠...
  5. CSS flex 布局里面的靠右对齐
  6. win11该文件没有与之关联的应用怎么办
  7. TN、HTN、STN、FSTN、DSTN、CSTN、TFT、LCD 的区别
  8. 电 脑 计 算 减 法 的 步 骤
  9. 电路分析 day01 一种使能控制电路
  10. 自动类型安全的REST .NET标准库refit