【三】静态链表

1、静态链表的定义

  • 顺序表数组中的元素由两个数据域组成:data和next;
  • data域用于存储数据;
  • next域用于存储下一个元素在数组中的下标;
  • 静态链表的大小是固定的;
  • 静态链表本质上就是一个结构体数组;

    这里写图片描述

静态链表是在顺序表的基础上利用数组实现的单链表!

2、相关数据结构定义

#ifdef WIN32
  typedef unsigned int LPDATA;
#else
  typedef unsigned long LPDATA;
#endif

/*
  LPDATA data; 成员用于保存被插入元素的地址,
              Windows下为4字节,Linux下为8字节
  int next; 成员用于保存下一个元素在数组中的下标,
            也可理解为相对于数组起始地址的相对地址
*/
typedef struct _struct_staticlistnode
{
  LPDATA data;
  int next;
}TStaticlistNode;

/*
  int capacity; 用于保存静态链表的最大容量
  TStaticlistNode header;  专门用于保存链表的头结点信息,
                  防止误操作或者丢失,是node[0]的一个拷贝
  TStaticlistNode node[]; 这里使用了C的柔性数组,
              node[0]中存放着当前链表的头结点信息
*/
typedef struct _struct_staticlist
{
  int capacity;
  TStaticlistNode header;
  TStaticlistNode node[];
}TStaticlist;

3、创建静态链表操作

/*
该方法用于创建并且返回一个空的线性表
*/
Staticlist* List_Create(int capacity)
{
  TStaticlist *tlist = NULL;
  if(capacity > 0)
  {
    /*
    柔性数组,TStaticlist结构体最后一个数据成员TStaticlistNode node[];没有指定数组
    大小,所以它是一个不完整的成员,sizeof(TStaticlist) 后得到的大小并不包含该成员;
    具体请参考我的博客中的[【C语言复习(二)】struct 与 union 的分析](http://blog.csdn.net/cmbug/article/details/30256043) 因为数组0号元素被用来存放数组头结点信息,所以这里要多分配一个空间:(capacity + 1)
    */
    tlist = (TStaticlist*)malloc(sizeof(TStaticlist) + sizeof(TStaticlistNode) *(capacity + 1));
  }
  if(tlist != NULL)
  {
    tlist->capacity = capacity;
    tlist->header.data = 0;
    tlist->header.next = 0;

//初次建立后,标记数组所有位置可用
    for(int i = 1; i<=capacity; i++)
    {
      tlist->node[i].next = AVAILABLE;
    }
  }
  return tlist;
}

4、插入元素操作

/*
该方法用于向一个线性表list的pos位置处插入新元素node
返回值为1表示插入成功,0表示插入失败
node 实际上是要被插入的元素的地址
pos 表示插入位置,从0开始计数
*/
int List_Insert(Staticlist* list, StaticlistNode* node, int pos)
{
  int iret = 1,emptyIndex = 0,current = 0;
  TStaticlist *tlist = (TStaticlist*)list;
  iret = iret && (tlist != NULL) && (node != NULL) && (pos >=0);
  if(iret)
  {
    //将头结点信息复制到数组的第一个位置
    tlist->node[0]  = tlist->header;

    //先找个空位置,把数据放进去
    for(int i = 1;i<=tlist->capacity;i++)
    {
      if(tlist->node[i].next == AVAILABLE)
      {
        emptyIndex = i;
        break;
      }
    }
    //放置要插入的数据,实际上是一个地址
    tlist->node[emptyIndex].data = (LPDATA)node;

    //再做排序操作
    /*(i<pos) && (tlist->node[current].next != 0)
    该条件保证了当要插入的位置大于了当前链表已有的数据长度时,将该元素插入到最后的位置,
    而不会跳跃插入*/
    for(int i = 0;(i<pos) && (tlist->node[current].next != 0);i++)
    {
      current = tlist->node[current].next;
    }
    tlist->node[emptyIndex].next = tlist->node[current].next;
    tlist->node[current].next = emptyIndex;

//更新链表的头结点数据,并及时拷贝备份到header中
    tlist->node[0].data++;
    tlist->header = tlist->node[0];
  }
  return iret;
}

5、获取元素操作

/*
该方法用于获取一个线性表list的pos位置处的元素
返回值为pos位置处的元素,NULL表示获取失败
*/
StaticlistNode* List_Get(Staticlist* list, int pos)
{
  TStaticlistNode *ret = NULL;
  int current = 0;
  TStaticlist *tlist = (TStaticlist*)list;
  if(tlist != NULL)
  {
    if(pos>=0 && pos < tlist->header.data)
    {
      tlist->node[0] = tlist->header;
      /*因为pos从0开始计数,而实际保存元素的位置是从数组的1号位置开始的,
      所以循环条件为:i<= pos
      */
      for(int i = 0;i<= pos;i++)
      {
        current = tlist->node[current].next;
      }
      //得到数据
      ret = (StaticlistNode*)tlist->node[current].data;
    }
  }
  return ret;
}

6、删除元素操作

/*
该方法用于删除一个线性表list的pos位置处的元素
返回值为被删除的元素,NULL表示删除失败
*/
StaticlistNode* List_Delete(Staticlist* list, int pos)
{
  TStaticlistNode *ret = NULL;
  int current = 0,delnode = 0;
  TStaticlist *tlist = (TStaticlist*)list;
  if(tlist != NULL)
  {
    if(pos >= 0 && pos < tlist->header.data)
    {
      //先找到要删除元素的前一个元素,因为等会要修正它的next成员数据
      for(int i = 0; i<pos;i++)
      {
        current = tlist->node[current].next;
      }
      //获取要被删除的元素
      delnode = tlist->node[current].next;
      //开始删除操作
      tlist->node[current].next = tlist->node[delnode].next;
      tlist->node[delnode].next = AVAILABLE;
      //得到被删除的元素的数据,用于返回
      ret = (StaticlistNode*)tlist->node[delnode].data;
      //更新头结点数据
      tlist->node[0].data--;
      tlist->header = tlist->node[0];
    }
  }
  return ret;
}

7、完整源码下载

文件名:staticlist-1.0.tar.gz
链接: http://pan.baidu.com/s/1c0lPo0S 密码: 58wq

编译步骤:
0.1 解压缩:tar -zxvf staticlist-1.0.tar.gz
0.2 进入目录:./configure
0.3 生成Seqlist:make
0.4 运行程序:./Staticlist

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值