暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

数据结构(严蔚敏C语言版)——线性表(静态链表)

编程Cookbook 2020-03-05
43

点击上方蓝字关注我!

如果有错误或者理解不到位的地方还请各位指正!

数据结构的相关问题,可以参考笔者写的系列数据结构文章,或者加我交流!

声明:以下内容是对清华大学出版社出版,由严蔚敏和吴伟民编著的图书《数据结构》(C语言版)的代码实现。
图书PDF版本可移步公众号【李歘歘】回复电子书领取。
《数据结构》(C语言版)是各大高校计算机有关专业的指定教材,还是计算机考研的统考专业课数据结构指定的参考书籍,数据结构作为408专业课的重中之重,值得大家重视。

上次说到了线性表的普通链表,今天我们来说一下有关静态链表,相关知识点请先自行了解。


书中位置(页码):P31-P34

函数定义及说明:

    void InitSpace_SL(SLinkList &space)  //创建备用列表 
    int Malloc_SL(SLinkList &space)  //提取分配空间(申请一个空闲结点)
    void Free_SL(SLinkList &space, int k)  //释放空闲结点
    void CreatList_SL(SLinkList &space,int n) //创建静态链表(书上的,就是标记最后一个结点的游标为0) 
    int LengthList_SL(SLinkList space)  //获取静态链表长度 
    void TraverseList_SL(SLinkList space)  //遍历静态链表
    void LocateElem_SL(SLinkList space,ElemType e)  //在静态链表中查找第1个值为e的元素
    void GetList_SL(SLinkList space,int i)  //用e返回线性表中第i个元素的值
    void ClearList_SL(SLinkList &space)  //清空链表
    Status ListInsert_SL(SLinkList &space,int i,ElemType e)  //在L中第i个元素之前插入数据元素e
    Status ListDelete_SL(SLinkList &space,int i,ElemType e)  //删除L中第i个元素,并返回其值
    Status PriorElem_SL(SLinkList space,ElemType cur_e,ElemType pre_e)  //查找前驱 cur_e不是第一个元素
    Status NextElem_Sq(SLinkList space,ElemType cur_e,ElemType next_e)  //查找后继元素  cur_e不是最后一个元素
    bool EmptyList_SL(SLinkList space)//判断是否为空

    程序代码:

      #include<cstdio>
      #include<cstdlib>
      #define MAXSIZE 1000 //链表的最大长度
      #define ElemType int
      #define Status int

      using namespace std;
      //静态链表的结构(数据域、游标)
      typedef struct {
      ElemType data; //数据域
      int cur; //游标域或者指针域
      }component,SLinkList[MAXSIZE];

      //创建备用列表
      void InitSpace_SL(SLinkList &space){
      //将一维数组space中分量链成一个备用备用链表,space[0].cur 为备用头指针
      //“0”表示空指针
      for(int i=0;i<MAXSIZE-1;i++){
      space[i].cur = i+1; //将每个数组分量链接到一起
      }
      //最后一个指针为0
      space[MAXSIZE-1].cur = 0;
      }

      //提取分配空间(申请一个空闲结点)
      int Malloc_SL(SLinkList &space){
      //若备用空间链表非空,则返回分配的结点下标,否则返回0
      int i = space[0].cur;
      if(space[0].cur)
      space[0].cur = space[i].cur;
      return i;
      }

      //释放空闲结点
      void Free_SL(SLinkList &space, int k){
      //将下标为k的空闲结点回收到备用链表
      space[k].cur = space[0].cur; //回收结点的“游标”指向备用链表的头结点之后节点(即第一个结点)
      space[0].cur = k; //备用链表的头结点指向新回收的结点
      }

      //创建静态链表(书上的,就是标记最后一个结点的游标为0)
      void CreatList_SL(SLinkList &space,int n){
      InitSpace_SL(space); //初始化备用空间
      int S = MAXSIZE-1;
      //将数组最后一个结点当做静态链表(非备用链表)的头结点
      int r=S; //r指向当前链表的最后结点
      for(int j=1;j<=n;j++){ //建立链表
      int i = Malloc_SL(space); //分配结点
      scanf("%d",&space[i].data); //输入元素值
      space[r].cur = i; //插入到表尾
      r=i; //更新表尾
      }
      space[r].cur = 0; //尾结点的指针为空
      printf("创建成功\n");
      }

      //获取静态链表长度
      int LengthList_SL(SLinkList space){
      int i=space[MAXSIZE-1].cur,count=0;
      while(i){
      i=space[i].cur;
      count++;
      }
      printf("长度为:%d\n",count);
      return count;
      }

      //遍历静态链表
      void TraverseList_SL(SLinkList space){
      printf("遍历链表:");
      int i = space[MAXSIZE-1].cur; //i指向表中的第1个结点的位序
      while(i) { //遍历
      printf("%d ",space[i].data);
      i = space[i].cur; //指向下一个元素
      }
      printf("\n");
      }

      //在静态链表中查找第1个值为e的元素
      void LocateElem_SL(SLinkList space,ElemType e){
      int i = space[MAXSIZE-1].cur; //i指向表中的第1个结点的位序
      int local = 1; //初始化其序为1
      while(i && (space[i].data != e)){ //当结点存在并且数据域不等于e
      i = space[i].cur; //指向下一个元素
      local++; //位序加1
      }
      if(i==0){ //如果i已经到了最后一个元素的游标(为0)则说明前面没有符合要求的元素值
      printf("该元素不存在\n");
      }else{
      printf("第一个值为%d的位序为:%d\n",e,local);
      }
      }

      //用e返回线性表中第i个元素的值
      void GetList_SL(SLinkList space,int i){
      int s=space[MAXSIZE-1].cur;
      int j=1;
      while(s && j<i){
      s=space[s].cur;
      j++;
      }
      if(s==0){ //如果i已经到了最后一个元素的游标(为0)则说明前面没有符合要求的元素值
      printf("位序错误\n");
      }else{
      printf("第%d个元素的值为:%d\n",i,space[s].data);
      }
      }

      //清空链表
      void ClearList_SL(SLinkList &space){
      int i = space[MAXSIZE-1].cur;
      while(i){
      int j = i;
      i = space[i].cur;
      Free_SL(space,j);
      }
      space[MAXSIZE-1].cur = 0;
      printf("清空链表成功\n");
      }

      //在L中第i个元素之前插入数据元素e
      Status ListInsert_SL(SLinkList &space,int i,ElemType e){
      if(i<1 || i> LengthList_SL(space)+1){ //检查插入位置是否正确
      printf("插入位置错误\n");
      return 0;
      }
      int j = Malloc_SL(space); //申请新结点
      int k = MAXSIZE-1;
      if(j){ //如果结点申请成功
      space[j].data = e; //赋值给结点
      for(int l=1;l<i;l++){ //找到第i-1个结点
      k = space[k].cur; //指向下一个结点
      }
      space[j].cur = space[k].cur; //新结点指向第i-1个元素后的元素
      space[k].cur = j; //第i-1个元素指向新结点
      }
      printf("插入成功\n");
      return 0;
      }

      //删除L中第i个元素,并返回其值
      Status ListDelete_SL(SLinkList &space,int i,ElemType e){
      if(i<1 || i> LengthList_SL(space)){ //检查插入位置是否正确
      printf("删除位置错误\n");
      return 0;
      }
      int k = MAXSIZE-1;
      for(int l=1;l<i;l++){ //找到第i-1个结点
      k = space[k].cur; //指向下一个结点
      }
      int j = space[k].cur; //j为将删除的结点
      space[k].cur = space[j].cur; //将i-1结点的指针域和i+1的指针域连接起来
      e = space[j].data; //赋值e
      Free_SL(space,j);
      printf("删除%d个元素%d成功\n",i,e);
      return 0;
      }

      //查找前驱 cur_e不是第一个元素
      Status PriorElem_SL(SLinkList space,ElemType cur_e,ElemType pre_e){
      int i = space[MAXSIZE-1].cur;
      if(cur_e == space[i].data){
      printf("第一个元素没有前驱\n");
      return 0;
      }
      while(i && cur_e != space[i].data){
      pre_e = space[i].data; //将前驱结点置为当前结点
      i = space[i].cur; //指向下一个结点
      }
      if(i==0){
      printf("该元素不存在\n");
      }else{
      printf("%d的前驱是%d\n",cur_e,pre_e);
      }
      return 0;
      }

      //查找后继元素 cur_e不是最后一个元素
      Status NextElem_Sq(SLinkList space,ElemType cur_e,ElemType next_e){
      int i = space[MAXSIZE-1].cur;
      int j; //用j标记查找的结点
      while(i && cur_e != space[i].data){
      i = space[i].cur; //指向下一个结点
      }
      if(i==0){
      printf("该元素不存在\n");
      }else{
      i = space[i].cur;
      if(i==0){
      printf("最后一个元素没有后继\n");
      }else{
      next_e = space[i].data;
      printf("%d的后继是%d\n",cur_e,next_e);
      }
      }
      return 0;
      }


      //判断是否为空
      bool EmptyList_SL(SLinkList space){
      if(space[MAXSIZE-1].cur==0){ //判断其链表的头指针的游标是否为0
      printf("链表为空\n");
      return true;
      }else{
      printf("链表不为空\n");
      return false;
      }
      }

      int main(){
      SLinkList space;
      int n,a,b,d,e,f,g,h,i,j,k;
      printf("请输入建立链表的元素个数:\n");
      scanf("%d",&n); //输入链表的个数
      CreatList_SL(space,n);
      EmptyList_SL(space);
      LengthList_SL(space);
      TraverseList_SL(space);
      printf("请输入查找的元素值:");
      scanf("%d",&a); //输入查找的元素值
      LocateElem_SL(space,a);
      printf("请输入查找的位序:");
      scanf("%d",&b); //输入查找的位序
      GetList_SL(space,b);
      printf("请输入插入的位序和值:");
      scanf("%d%d",&d,&e); //输入插入的位序和值
      ListInsert_SL(space,d,e);
      TraverseList_SL(space);
      LengthList_SL(space);
      printf("请输入删除的位序:");
      scanf("%d",&f);
      ListDelete_SL(space,f,g);
      TraverseList_SL(space);
      LengthList_SL(space);
      printf("请输入查找的元素(返回其前驱):");
      scanf("%d",&h);
      PriorElem_SL(space,h,i);
      printf("请输入查找的元素(返回其后继):");
      scanf("%d",&j);
      NextElem_Sq(space,j,k);
      ClearList_SL(space);
      return 0;
      }
      ————————————————
      版权声明:本文为CSDN博主「李歘歘」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
      原文链接:https://lichuachua.blog.csdn.net/article/details/104507777

      运行结果:


      「往  •  期  •  精  •  选」

          

      程序员自学攻略——分享珍藏多年的学习网站

      在B站,我看到了不同的技术人生

      数据结构(严蔚敏C语言版)——线性表(普通链表)

      数据结构(严蔚敏C语言版)——线性表(顺序表)

      原谅我,是我不配!!!

      技术分享的优势——写文章半年的收获

      考研VS就业——选一条适合自己的路

      这些经典排序,你必须掌握
      最短路径——Dijkstra算法这一篇就够了

      全源最短路径问题——Floyd算法

      在看点这里
      文章转载自编程Cookbook,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论