基本数据结构之线性表-顺序表

数据结构有线性结构和非线性结构之分,本数据结构系列将从线性结构讲到非线性结构,并对这些数据结构进行精简实现(C/C++)。

1、线性结构之线性表

      线性表是这样一种结构,它包含n(n>=0)个数据元素,每个数据元素成为线性表的结点;其中a[0],a[1],a[2]......,a[n-1]组成的有限序列。

  1. 数据元素的个数n称为线性表的长度 = list.length(),当长度为空时,成为空表。
  2. 将非空的(n>0)线性表表示为:a[0],a[1],a[2]......,a[n-1].
  3. 其中数据元素a[i]只是一个抽象符号,具体元素是什么类型要看具体的情况。

     一个数据元素并不要求是原子的,可以有若干数据项组成。每个数据元素成为记录,含有大量记录的线性表又称为文件。这种结构必须具有以下特点:存在一个唯一的没有前驱的(头)数据元素;存在一个唯一的没有后继的(尾)数据元素;此外,每一个数据元素均有一个直接前驱和一个直接后继数据元素。

2、线性表的存储结构

     2.1 顺序表

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

      下面介绍顺序表的C语言实现。

 
 
/*
* @function the basic operation on List
* @author lz
* @date 2013.8.18
*/
//线性表的动态分配存储结构
#define LIST_INIT_SIZE 10 /* 线性表存储空间的初始分配量 */
#define LIST_INCREMENT 2 /* 线性表存储空间的分配增量 */
typedef struct
{
   ElemType * elem ; /* 存储空间基址 */
   int length ; /* 当前长度 */
   int listsize ; /* 当前分配的存储容量(以sizeof(ElemType)为单位) */
} SqList ;
//基本操作
/* 顺序表示的线性表的基本操作(12个) */
void InitList ( SqList * L )
{ /* 操作结果: 构造一个空的顺序线性表L */
   L -> elem = malloc ( LIST_INIT_SIZE * sizeof ( ElemType ));
   if ( ! L -> elem )
     exit (1 ); /* 存储分配失败 */
   L -> length = 0 ; /* 空表长度为0 */
   L -> listsize = LIST_INIT_SIZE ; /* 初始存储容量 */
}
/* 初始条件:顺序线性表L已经存在.操作结果:销毁线性表L */
void DestroyList ( SqList * L )
{
   free ( L -> elem );
   L -> elem = NULL ;
   L -> length = 0 ;
   L -> listsize = 0 ;
}
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
void ClearList ( SqList * L )
{
   L -> length = 0 ;
}
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty ( SqList L )
{
   if ( L . length == 0 )
     return TRUE ;
   else
     return FALSE ;
}
/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
int ListLength ( SqList L )
{
   return L . length ;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)。操作结果:用e返回L中第i个数据元素的值 */
Status GetElem ( SqList L , int i , ElemType * e )
{
   if ( i < 1 || i > L . length )
     return ERROR ;
   * e = ( L . elem + i - 1 );
   return OK ;
}
/* 初始条件:顺序线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) */
/* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0。 */
int LocateElem ( SqList L , ElemType e , Status ( * compare )( ElemType , ElemType ))
{
   ElemType * p ;
   int i = 1 ; /* i的初始值为第一个元素的位置 */
   p = L . elem ; /* p的初始值为第一个元素的存储位置 */
  
   while ( i <= L . length && ! compare ( * p ++ , e ))
     ++ i ;
   if ( i <= L . length )
     return i ;
   else
     return 0 ;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
/* 否则操作失败,pre_e无定义 */
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 ;
   }
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
/* 否则操作失败,next_e无定义 */
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 ;
   }
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)+1 */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Status ListInsert ( SqList * L , int i , ElemType e )
{
   ElemType * newbase , * p , * q ;
  
   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 (1 ); /* 存储分配失败 */
     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 ;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
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 ;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素调用函数vi() */
/* vi()的形参加'&',表明可通过调用vi()改变元素的值 */
void ListTraverse ( SqList L , void ( * vi )( ElemType * ))
{
   ElemType * p ;
   int i ;
   p = L . elem ;
   for ( i = 1 ; i <= L . length ; i ++ )
     vi ( p ++ );
   printf ( " \n " );
}


----------------------------------------------------------------------------------------华丽的分割线----------------------------------------------------------------------------------------------------------------------------



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值