线性表(顺序表)

线性表的定义


线性表是由(n>=0)个数据元素(结点)a[0],a[1],a[2]……a[n-1]
组成的有限序列。其中,一个数据元素可以由若干个数据项组成。数据元素称为记录,含有大量记录的线性表称为文件。
线性表存在以下特点

  • 存在一个唯一没有前驱(头)的数据元素
  • 存在一个唯一没有后继(尾)的数据元素
  • 此外,所有数据元素都有一个前驱和后继

线性表的存储结构

1 顺序表
2 链表

  • 单链表(动态单链表,静态单链表)
  • 双链表
  • 循环链表(单循环链表,双循环链表)

下面来学习线性表的顺序表。

什么是顺序表

顺序表是在计算机内存中以数组的形式保存的线性表,是指使用一组地址连续的存储单元来存储数据元素的线性结构。

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

/* 线性表的动态分配顺序存储结构 */
#define LIST_INIT_SIZE 10 /* 线性表存储空间的初始分配量 */
#define LIST_INCREMENT 2 /* 线性表存储空间的分配增量 */
typedef struct
{
  ElemType *elem;/*存储空间基址*/
  int length;/*当前长度*/
  int listsize;/*当前分配的存储容量(以sizeof(ElemType)为单位) */
}Sqlist;

/**
 *线性表的基本操作
 * 增删改查
 */

/**
 * 构造一个空的顺序线性表L
 * @brief InitSqlist
 * @param L
 */
void InitSqlist(Sqlist *L){

    L->elem=malloc(LIST_INIT_SIZE*sizeof(ElemType)); /* 存储单元的地址是连续的 */
    if(!L->elem)
        exit(OVERFLOW);/* 分配空间失败 */
    L->length=0; /* 空表长度为0 */
    L->listsize=LIST_INIT_SIZE; /* 初始存储容量 */

}
/** 初始条件:顺序线性表L已存在。销毁顺序线性表L
  * @brief DestroySqlist
  * @param L
  */
 void DestroySqlist(Sqlist * L){

     free(L->elem);
     L->elem=NULL;
     L->length=0;
     L->listsize=0;
 }
/** 清除表中所有元素
 * @brief ClearSqlist
 * @param L
 */
void ClearSqlist(Sqlist *L){
    L->length=0;
}
/** 判断表是否为空
 * @return
 */
Status ListEmpty(Sqlist *L){

    if(L->length=0)
        return TRUE;
    return FALSE;

}
/** 返回L中数据元素个数
 * @brief ListLength
 * @param L
 * @return
 */
int ListLength(SqList L)
{
  return L.length;
}
/**  获取指定位置的数据元素
 * @brief GetElem
 * @param L
 * @param position 数据元素在顺序表的位置(第一个是1,第二个是2……)
 * @param e
 * @return
 */
Status GetElem(Sqlist L,int position,ElemType *e){

    if(position<1||position>L.length)
        return ERROR;
    *e=*(L.elem+position-1);
    return OK;

}
/** 返回指定元素的位置
  * @brief LocateElem
  * @param L
  * @param e 指定元素
  * @return
  */
 int LocateElem(Sqlist *L, ElemType e,Status(*compare)(ElemType,ElemType)){
     /* compare()是数据元素判定函数(满足为1,否则为0) */
     ElemType *p;
       int i=1; /* i的初值为第1个元素的位序 */
       p=L->elem; /* p的初值为第1个元素的存储位置 */
       while(i<=L->length&&!compare(*p++,e))
         ++i;
       if(i<=L->length)
         return i;
       else
         return 0;
 }
 /**
  * @brief PriorElem
  * @param L
  * @param cur_e 当前元素
  * @param pre_e 前驱
  * @return
  */
 Status PriorElem(Sqlist L,ElemType cur_e,ElemType *pre_e)
 {
   int i=2;
   ElemType *p=L.elem+1;
   while(i<=L.length&&*p!=cur_e)
   {/*?为什么前面使用函数指针,但是此却却直接使用值比较呢?*/
     p++;
     i++;
   }
   if(i>L.length)
     return INFEASIBLE; /* 操作失败 */
   else
   {
     *pre_e=*--p;
     return OK;
   }
 }
 /**
  * @brief NextElem
  * @param L
  * @param cur_e 当前元素
  * @param next_e 后继
  * @return
  */
 Status NextElem(Sqlist L,ElemType cur_e,ElemType *next_e)
 {
   int i=1;
   ElemType *p=L.elem;
   while(i<L.length&&*p!=cur_e)
   {
     i++;
     p++;
   }
   if(i==L.length)
     return INFEASIBLE; /* 操作失败 */
   else
   {
     *next_e=*++p;
     return OK;
   }
 }
 /**
  * 插入操作需要判断插入位置是否合法,表的存储空间是否满
  * 插入位置不合法就返回错误信息,满表则需要增加表的存储空间
  * @brief ListInsert
  * @param L
  * @param i
  * @param e
  * @return
  */
 Status ListInsert(Sqlist *L,int i,ElemType e)
 {
   ElemType *newbase,*q,*p;
   if(i<1||i>L->length+1) /* i值不合法 */
     return ERROR;
   if(L->length>=L->listsize) /* 当前存储空间已满,增加分配 */
   {
     newbase=realloc(L->elem,(L->listsize+LIST_INCREMENT)*sizeof(ElemType));
     if(!newbase)
       exit(OVERFLOW); /* 存储分配失败 */
     L->elem=newbase; /* 新基址 */
     L->listsize+=LIST_INCREMENT; /* 增加存储容量 */
   }
   q=L->elem+i-1; /* q为插入位置 */
   for(p=L->elem+L->length-1;p>=q;--p) /* 插入位置及之后的元素右移 */
     *(p+1)=*p;
   *q=e; /* 插入e */
   ++L->length; /* 表长增1 */
   return OK;
 }
 /** 删除表指定元素
  * @brief ListDelete
  * @param L
  * @param i
  * @param e
  * @return
  */
 Status ListDelete(Sqlist *L,int i,ElemType *e)
 {
   ElemType *p,*q;
   if(i<1||i>L->length) /* i值不合法 */
     return ERROR;
   p=L->elem+i-1; /* p为被删除元素的位置 */
   *e=*p; /* 被删除元素的值赋给e */
   q=L->elem+L->length-1; /* 表尾元素的位置 */
   for(++p;p<=q;++p) /* 被删除元素之后的元素左移 */
     *(p-1)=*p;
   L->length--; /* 表长减1 */
   return OK;
 }











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值