1,我们研究数据结构的操作,第一要弄懂它的结构体表示(也就是结构体特点)、第二要清楚它的初始化和撤销过程。对于静态链表首先分析它的特点:一是采用静态存储方式,二是没有指针。静态链表就是不用指针来表示链式关系的一种巧妙实现。

2,静态链表的结构体定义

  1. 1 #define MAX 100
  2. 2
  3. 3 typedef struct
  4. 4 {
  5. 5 int data; //数据域的类型可以是任意的基类型,包括数组
  6. 6 int cur;
  7. 7 }component, slinklist[MAX]

3,静态链表的初始化示意图

4,静态链表的操作集合,与单链表一致,均在头文件defs.h中。此头文件在前面文章中已经写出。

5,初始化操作的实现

  1. 1 #include"defs.h"
  2. 2
  3. 3 void InitList(slinklist s)
  4. 4 {
  5. 5 int i;
  6. 6 L[MAX-1].cur = 0; //令链表头结点为空
  7. 7
  8. 8 for (i=0; i<MAX-2; i++) //其余元素构成备用链表
  9. 9 L[i].cur = i+1;
  10. 10 L[MAX-2].cur = 0; //备用链表最后一个元素置为空
  11. 11 }

InitList.c

6,静态链表撤销操作的实现,原理就是将链表从第一个元素至最后一个元素插入到备用链表第一个元素前

  1. 1 #include"defs.h"
  2. 2
  3. 3 void DestroyList(slinklist s)
  4. 4 {
  5. 5 int i = L[MAX-1].cur;
  6. 6 L[MAX-1].cur = 0; //令头结点指向空
  7. 7
  8. 8 int k = L[0].cur;
  9. 9 L[0].cur = i; //令备用链表头结点指向链表第一个结点
  10. 10
  11. 11 int j; //用j来记录链表最后一个结点的位序
  12. 12 while (i)
  13. 13 {
  14. 14 j = i;
  15. 15 i = L[i].cur; //第i个结点的指针域为空,结束循环,j记录了最后一个结点
  16. 16 }
  17. 17 L[j].cur = k; //令链表最后一个结点指向备用链表第一个结点
  18. 18 }

DestroyList.c

7,静态链表清空操作和撤销操作是一致的。
8,判断空操作。ListEmpty.c

  1. 1 #include"defs.h"
  2. 2
  3. 3 int ListEmpty(slinklist s)
  4. 4 {
  5. 5 if (L[MAX-1].cur == 0)
  6. 6 return 0; //返回0代表为空
  7. 7 else
  8. 8 return 1; //非0代表不为空
  9. 9 }

ListEmpty.c

9,求链表长度操作.

  1. 1 #include"defs.h"
  2. 2
  3. 3 int ListLength(slinklist s)
  4. 4 {
  5. 5 int i, j=0;
  6. 6 i = L[MAX-1].cur; //i指向第一个结点
  7. 7
  8. 8 while (i) //最后一个结点的指针域为空,结束循环
  9. 9 {
  10. 10 ++j;
  11. 11 i = L[i].cur;
  12. 12 }
  13. 13 return j;
  14. 14 }

ListLength.c

10,取元素操作.

  1. 1 #include"defs.h"
  2. 2
  3. 3 int GetElem(slinklist s, int i, int *e)
  4. 4 {
  5. 5 int j=1, k = L[MAX-1].cur;
  6. 6 if (i<1 || i>ListLength(s)) //判断位置是否合理
  7. 7 exit(0);
  8. 8 while (k && j<i) //找到第i个位置
  9. 9 {
  10. 10 ++j;
  11. 11 k = L[k].cur;
  12. 12 }
  13. 13 *e = L[k].data;
  14. 14 return 0;
  15. 15 }

GetElem.c

11,查找元素操作实现.

  1. 1 #include"defs.h"
  2. 2
  3. 3 int LocateElem(slinklist s, int e)
  4. 4 {
  5. 5 int i = L[MAX-1].cur;
  6. 6 int j = 0;
  7. 7 while (i)
  8. 8 {
  9. 9 ++j; //j作为计数器
  10. 10 if (L[i].data == e)
  11. 11 return j;
  12. 12 i = L[i].cur;
  13. 13 }
  14. 14 return 0;
  15. 15 }
  16. 16
  17. 17 //i仅是表示其元素的数组下标值,并不是位序

LocateElem.c

12,求前驱操作实现.

  1. 1 #include"defs.h"
  2. 2
  3. 3 int PriorElem(slinklist L, int cur_e, int *pri_e)
  4. 4 {
  5. 5 int i = L[MAX-1].cur;
  6. 6 int j;
  7. 7 while (i)
  8. 8 {
  9. 9 j = L[i].cur;
  10. 10 if (j && L[j].data == cur_e)
  11. 11 {
  12. 12 *pri_e = L[i].data;
  13. 13 return 0;
  14. 14 }
  15. 15 i = j;
  16. 16 }
  17. 17 return 0;
  18. 18 }

PriorElem.c

13,求后继操作的实现

  1. 1 #include"defs.h"
  2. 2
  3. 3 int NextElem(slinklist L, int cur_e, int *nex_e)
  4. 4 {
  5. 5 int i = L[MAX-1].cur;
  6. 6 int j;
  7. 7 while (i)
  8. 8 {
  9. 9 j = L[i].cur;
  10. 10 if (j && L[i].data == cur_e)
  11. 11 {
  12. 12 *nex_e = L[j].data;
  13. 13 return 0;
  14. 14 }
  15. 15 i = j;
  16. 16 }
  17. 17 return 0;
  18. 18 }

NextElem.c

14,Malloc函数实现

  1. 1 //因为没有指针,没有动态分配函数,所以要自己实现
  2. 2
  3. 3 #include"defs.h"
  4. 4
  5. 5 int Malloc(slinklist L) //释放备用链表第一个结点
  6. 6 {
  7. 7 int i = L[0].cur;
  8. 8 if (i == 0) //备用链表为空,无法分配,退出
  9. 9 exit(0);
  10. 10 L[0].cur = L[i].cur; //备用链表头结点,指向备用链表第二个结点
  11. 11 return i;
  12. 12 }

15,Free函数实现

  1. 1 #include"defs.h"
  2. 2
  3. 3 void Free(slinklist L, int k) //将位置为k的空闲结点释放
  4. 4 { //即插入到备用链表第一个结点前
  5. 5 L[k].cur = L[0].cur;
  6. 6 L[0].cur = k;
  7. 7 }
  8. 8
  9. 9 //Malloc、Free均是对备用链表的操作

16,静态链表插入操作实现

  1. 1 #include"defs.h"
  2. 2
  3. 3 int ListInsert(slinklist L, int i, int e)
  4. 4 {
  5. 5 int k = L[MAX-1].cur; //k指向第一个结点
  6. 6 int j = 1, m, s;
  7. 7
  8. 8 if (i<1 || i>ListLength(L)+1) //判断位置是否合理
  9. 9 exit(0);
  10. 10
  11. 11 while (k && j<i-1) //找到第i-1个位置
  12. 12 {
  13. 13 ++j;
  14. 14 k = L[k].cur;
  15. 15 }
  16. 16 m = L[k].cur; //m指向第i个位置
  17. 17
  18. 18 s = Malloc(L); //分配一个结点s
  19. 19 L[s].data = e;
  20. 20 L[s].cur = L[m].cur;
  21. 21 L[k].cur = s;
  22. 22 return 0;
  23. 23 }

ListInsert.c

17,静态链表删除操作的实现

  1. 1 #include"defs.h"
  2. 2
  3. 3 int ListDelete(slinklist L, int i, int *e)
  4. 4 {
  5. 5 int k = L[MAX-1].cur;
  6. 6 int j = 1, m;
  7. 7 if (i<1 || i>ListLength(L)) //判断位置是否合理
  8. 8 exit(0);
  9. 9
  10. 10 while (k && j<i-1) //找到第i-1个位置
  11. 11 {
  12. 12 ++j;
  13. 13 k = L[k].cur;
  14. 14 }
  15. 15 m = L[k].cur; //m指向第i个位置
  16. 16 *e = L[m].data;
  17. 17 L[k].cur = L[m].cur;
  18. 18 Free(L, m); //将空闲结点m释放到备用链表中
  19. 19 }

ListDelete.c

18,遍历静态链表操作实现

  1. 1 #include"defs.h"
  2. 2
  3. 3 void TravelList(slinklist L)
  4. 4 {
  5. 5 int j = 0;
  6. 6 int i = L[MAX-1].cur;
  7. 7
  8. 8 while (i)
  9. 9 {
  10. 10 ++j;
  11. 11 printf("第%d个结点为:%d\n", j, L[i].data);
  12. 12 i = L[i].cur;
  13. 13 }
  14. 14 }

TravelList.c

C语言实现--静态链表的操作的更多相关文章

  1. 使用C语言描述静态链表和动态链表

    静态链表和动态链表是线性表链式存储结构的两种不同的表示方式. 静态链表的初始长度一般是固定的,在做插入和删除操作时不需要移动元素,仅需修改指针,故仍具有链式存储结构的主要优点. 动态链表是相对于静态链 ...

  2. 数据结构(C语言版)链表相关操作算法的代码实现

    这次实现的是带头结点的单链表的初始化.遍历.创建.插入.删除.判断链表是否为空.求链表长度函数,编译环境是vs2013. 其中插入和删除函数中循环的条件目前还不太明白. #include<ios ...

  3. 静态链表-C语言实现

    1.静态链表是在没有指针的编程语言里对链表的一种实现2.主要是用数组模拟指针3.在这里,使用结构体使数组的每一个空间可以存储一个数据元素(date)和一个游标(cur),游标的作用相当于链表的指针域, ...

  4. 静态链表 C语言描述

    静态链表1.下标为0的游标存放最后存放数据节点的游标,即是第一个没有存放元素(备用链表)的下标2.最后一个的节点存放第一个由数值得下标3.第一个和最后一个都不存放数据 即是备用链表的第一个的下标 4. ...

  5. 深入浅出数据结构C语言版(5)——链表的操作

    上一次我们从什么是表一直讲到了链表该怎么实现的想法上:http://www.cnblogs.com/mm93/p/6574912.html 而这一次我们就要实现所说的承诺,即实现链表应有的操作(至于游 ...

  6. 数据结构6: 静态链表及C语言实现

    本节继续介绍线性表的另外一种链式表示——静态链表.(前面介绍的链表称为 动态链表 ). 逻辑结构上相邻的数据元素,存储在指定的一块内存空间中,数据元素只允许在这块内存空间中随机存放,这样的存储结构生成 ...

  7. C语言提高 (6) 第六天 文件(续) 链表的操作

    1昨日回顾 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include &l ...

  8. C语言之----面向对象的方法实现链表的操作

    1 /* 2 * 详细运行过程: 本程序实现的是对链表的简单的操作,即链表的增 删 改 查 销毁 初始化 3 * 运用面向对象的思想,实现一个类op,op中包括了所有的链表操作方法 4 * 其他的程序 ...

  9. 玩转C语言链表-链表各类操作详解

    链表概述 链表是一种常见的重要的数据结构.它是动态地进行存储分配的一种结构.它可以根据需要开辟内存单元.链表有一个"头指针"变量,以head表示,它存放一个地址.该地址指向一个元素 ...

随机推荐

  1. mysql 连接url中需要添加useUnicode=true&characterEncoding=UTF-8

    下面是示例: 数据库中Username是张三 在数据库配置时没有配置编码  useUnicode=true&characterEncoding=UTF-8 导致期望与实际不同 配置useUni ...

  2. 【MyBatis】MyBatis 动态 SQL

    MyBatis 动态SQL if 可以根据实体类的不同取值,使用不同的 SQL 语句来进行查询. 使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分. 持久层 DAO 接口: pub ...

  3. mmall商城分类模块总结

    后台分类model的开发具体功能有:添加分类名称,修改分类名称,查询所有子分类,查询父分类以及它下面的子分类(递归) 需要注意的是,在后台管理进行操作的时候,都需要验证当前用户是否是管理员的角色,不管 ...

  4. mysql .sock丢时候如何链接数据库

    在mysql服务器本机上链接mysql数据库时,经常会噢出现mysql.sock不存在,导致无法链接的问题,这是因为如果指定localhost作为一个主机名,则mysqladmin默认使用unix套接 ...

  5. QLibrary 加载动态库

    阅读本文大概需要 6.6分钟 一般情况下在没有头文件支持情况下,想要引入某个动态库,最好的办法就是使用「动态加载」的方法,在Qt中一般使用QLibyary来操作 常用 api QLibrary(con ...

  6. leetcode 1593. 拆分字符串使唯一子字符串的数目最大(DFS,剪枝)

    题目链接 leetcode 1593. 拆分字符串使唯一子字符串的数目最大 题意: 给你一个字符串 s ,请你拆分该字符串,并返回拆分后唯一子字符串的最大数目. 字符串 s 拆分后可以得到若干 非空子 ...

  7. 使用sqluldr2进行oracle数据库抽取时执行后无反应,也无日志

    使用sqluldr2进行oracle数据库表数据抽取时遇到执行后无反应,也不报错,也无日志输出的情况. 经过排查之后发现时由于oracle账户密码快要过期导致的(这也能出问题,我服,类似的plsql连 ...

  8. Windows DHCP最佳实践(四)

    这是Windows DHCP最佳实践和技巧的最终指南. 如果您有任何最佳做法或技巧,请在下面的评论中发布它们. 在本指南(四)中,我将分享以下DHCP最佳实践和技巧. 使用DHCP中继代理 防止恶意D ...

  9. ctfhub技能树—文件上传—前端验证

    打开靶机 查看页面信息 尝试直接上传一句话木马 提示不允许上传 查看源码 发现仅允许上传.jpg,.png,.gif三种格式的文件 上传shell.jpg并使用burpsuite抓取数据包 添加完成后 ...

  10. 使用 TensorBoard 可视化模型、数据和训练

    使用 TensorBoard 可视化模型.数据和训练 在 60 Minutes Blitz 中,我们展示了如何加载数据,并把数据送到我们继承 nn.Module 类的模型,在训练数据上训练模型,并在测 ...