《数据结构》-静态链表的表示及实现

#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>

// 函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1

typedef int Status;  // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE
typedef int ElemType;

#define MAX_SIZE 100 // 链表的最大长度
typedef struct
{
  ElemType data;
  int cur;
} component, SLinkList[MAX_SIZE];

// 一个数组只生成一个静态链表的基本操作(11个)),包括算法2.13
#define DestroyList ClearList // DestroyList()和ClearList()的操作是一样的

int Malloc(SLinkList space) // 算法2.15
{                           // 若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回0
  int i = space[0].cur;
  if (i)                         // 备用链表非空
    space[0].cur = space[i].cur; // 备用链表的头结点指向原备用链表的第二个结点
  return i;                      // 返回新开辟结点的坐标
}

void Free(SLinkList space, int k) // 算法2.16
{                                 // 将下标为k的空闲结点回收到备用链表(成为备用链表的第一个结点)
  space[k].cur = space[0].cur;    // 回收结点的"游标"指向备用链表的第一个结点
  space[0].cur = k;               // 备用链表的头结点指向新回收的结点
}

void InitList(SLinkList L)
{ // 构造一个空的链表L,表头为L的最后一个单元L[MAX_SIZE-1],其余单元链成
  // 一个备用链表,表头为L的第一个单元L[0],“0”表示空指针
  int i;
  L[MAX_SIZE - 1].cur = 0;           // L的最后一个单元为空链表的表头
  for (i = 0; i < MAX_SIZE - 2; i++) // 将其余单元链接成以L[0]为表头的备用链表
    L[i].cur = i + 1;
  L[MAX_SIZE - 2].cur = 0;
}

void ClearList(SLinkList L)
{ // 初始条件:线性表L已存在。操作结果:将L重置为空表
  int i, j, k;
  i = L[MAX_SIZE - 1].cur; // 链表第一个结点的位置
  L[MAX_SIZE - 1].cur = 0; // 链表空
  k = L[0].cur;            // 备用链表第一个结点的位置
  L[0].cur = i;            // 把链表的结点连到备用链表的表头
  while (i)                // 没到链表尾
  {
    j = i;
    i = L[i].cur; // 指向下一个元素
  }
  L[j].cur = k; // 备用链表的第一个结点接到链表的尾部
}

Status ListEmpty(SLinkList L)
{                               // 若L是空表,返回TRUE;否则返回FALSE
  if (L[MAX_SIZE - 1].cur == 0) // 空表
    return TRUE;
  else
    return FALSE;
}

int ListLength(SLinkList L)
{                                     // 返回L中数据元素个数
  int j = 0, i = L[MAX_SIZE - 1].cur; // i指向第一个元素
  while (i)                           // 没到静态链表尾
  {
    i = L[i].cur; // 指向下一个元素
    j++;
  }
  return j;
}

Status GetElem(SLinkList L, int i, ElemType *e)
{                          // 用e返回L中第i个元素的值
  int l, k = MAX_SIZE - 1; // k指向表头序号
  if (i < 1 || i > ListLength(L))
    return ERROR;
  for (l = 1; l <= i; l++) // 移动到第i个元素处
    k = L[k].cur;
  *e = L[k].data;
  return OK;
}

int LocateElem(SLinkList L, ElemType e) // 算法2.13(有改动)
{                                       // 在静态单链线性表L中查找第1个值为e的元素。若找到,则返回它在L中的
  // 位序,否则返回0。(与其它LocateElem()的定义不同)
  int i = L[MAX_SIZE - 1].cur; // i指示表中第一个结点
  while (i && L[i].data != e)  // 在表中顺链查找(e不能是字符串)
    i = L[i].cur;
  return i;
}

Status PriorElem(SLinkList L, ElemType cur_e, ElemType *pre_e)
{ // 初始条件:线性表L已存在
  // 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,
  //           否则操作失败,pre_e无定义
  int j, i = L[MAX_SIZE - 1].cur; // i指示链表第一个结点的位置
  do
  { // 向后移动结点
    j = i;
    i = L[i].cur;
  } while (i && cur_e != L[i].data);
  if (i) // 找到该元素
  {
    *pre_e = L[j].data;
    return OK;
  }
  return ERROR;
}

Status NextElem(SLinkList L, ElemType cur_e, ElemType *next_e)
{ // 初始条件:线性表L已存在
  // 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,
  //           否则操作失败,next_e无定义
  int j, i = LocateElem(L, cur_e); // 在L中查找第一个值为cur_e的元素的位置
  if (i)                           // L中存在元素cur_e
  {
    j = L[i].cur; // cur_e的后继的位置
    if (j)        // cur_e有后继
    {
      *next_e = L[j].data;
      return OK; // cur_e元素有后继
    }
  }
  return ERROR; // L不存在cur_e元素,cur_e元素无后继
}

Status ListInsert(SLinkList L, int i, ElemType e)
{                             // 在L中第i个元素之前插入新的数据元素e
  int l, j, k = MAX_SIZE - 1; // k指向表头
  if (i < 1 || i > ListLength(L) + 1)
    return ERROR;
  j = Malloc(L); // 申请新单元
  if (j)         // 申请成功
  {
    L[j].data = e;          // 赋值给新单元
    for (l = 1; l < i; l++) // 移动i-1个元素
      k = L[k].cur;
    L[j].cur = L[k].cur;
    L[k].cur = j;
    return OK;
  }
  return ERROR;
}

Status ListDelete(SLinkList L, int i, ElemType *e)
{                          // 删除在L中第i个数据元素e,并返回其值
  int j, k = MAX_SIZE - 1; // k指向表头
  if (i < 1 || i > ListLength(L))
    return ERROR;
  for (j = 1; j < i; j++) // 移动i-1个元素
    k = L[k].cur;
  j = L[k].cur;
  L[k].cur = L[j].cur;
  *e = L[j].data;
  Free(L, j);
  return OK;
}

void ListTraverse(SLinkList L, void (*vi)(ElemType))
{                              // 初始条件:线性表L已存在。操作结果:依次对L的每个数据元素调用函数vi()
  int i = L[MAX_SIZE - 1].cur; // 指向第一个元素
  while (i)                    // 没到静态链表尾
  {
    vi(L[i].data); // 调用vi()
    i = L[i].cur;  // 指向下一个元素
  }
  printf("\n");
}

void print2(ElemType c)
{
  printf("%d ", c);
}

void main(int argc, char argv[])
{
  int k;
  SLinkList s;
  InitList(s);
  ListInsert(s, 1, 8);
  ListInsert(s, 2, 6);
  ListInsert(s, 3, 4);
  ListInsert(s, 4, 2);
  ListInsert(s, 5, 1);
  ListTraverse(s, print2);
  printf("%d \r\n", ListLength(s));

  ElemType e;
  ListDelete(s, 4, &e);
  printf("%d\r\n", e);
  ListTraverse(s, print2);

  printf("end\r\n");
  while (1);
}
/* output
8 6 4 2 1
5
2
8 6 4 1
end
*/

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值