数据结构:线性表(顺序表)

1、线性表

(1)定义

具有相同特性的数据元素的一个优先序列

第一个元素是起始结点,最后一个叫做终端结点

a结点的前一个结点叫做直接前驱,后一个结点叫做直接后继

元素可以是简单类型也可以是复杂类型(如:学生)的

2、线性表的顺序存储

(1)概念

把逻辑相邻的数据元素存储在物理上相邻的存储单元中的存储结构

第一个元素的存储位置称作起始地址或基地址

知道某一个元素的存储位置,就可以计算其他元素的存储位置

可以用一维数组定义线性表

(2)初始化和类型定义

初始化参数用引用:

Status InitList_Sq(SqList &L)                   //构造一 个空的顺序表L
{
    L.elem=new ElemType[MAXSIZE];   //为顺序表分配空间
    if(!L.elem) exit(OVERFLOW);           //存储分配失败
    L.length=0;                     //空表长度为0
    return OK;
}

初始化参数用指针:

Status InitList_Sq(SqList *L) //构造一个空的顺序表L
{
    L-> elem=new ElemType[MAXSIZE];   //为顺序表分配空间
    if(! L-> elem) exit(OVERFLOW);       //存储分配失败
    L-> length=0;                      //空表长度为0
    return OK;
}

顺序表的类型定义:

typedef struct{
  ElemType data[];
  int length;
}SqList;

由存放数据的数组和个数的元素组成,ElemType是元素的类型,实际运用的时候需要替换,如:

typedef struct Node {            //定义表结点
    char classRoomNum[10];        //教室编号 
    char freeTime1[10];            //空闲时间段 1
    char freeTime2[10];            //空闲时间段 2 
    char freeTime3[10];            //空闲时间段 3 
    char freeTime4[10];            //空闲时间段 4 把一天分为四个时间段 
    char set[10];                //教室地点 
    int volume;                    //容量 
    struct Node *next;
} SLNode;

(3)销毁和清空

销毁:

void DestroyList(SqList &L)
{
  if (L.elem) delete[]L.elem;   
 //释放存储空间
}

清空:

void ClearList(SqList &L) 
{
   L.length=0;               
 //将线性表的长度置为0
}

(4)求长度

int GetLength(SqList L)
{
   return (L.length);             
}

(5)判断是否为空

int IsEmpty(SqList L)
{
  if (L.length==0) return 1;      
   else return 0;
}

3、线性表的基本操作

(1)取值

int GetElem(SqList L,int i,ElemType &e)
{
  if (i<1||i>L.length) return ERROR;   
   //判断i值是否合理,若不合理,返回ERROR
  e=L.elem[i-1];   //第i-1的单元存储着第i个数据
  return OK;
}
(2)查找:在线性表L中查找值为e的数据元素
int LocateELem(SqList L,ElemType e)
{
      for (i=0;i< L.length;i++)
          if (L.elem[i]==e) return i+1;                
      return 0;
}
时间复杂度为O(n),空间复杂度为O(1),因为他没有占用任何的辅助空间

(3)添加:在线性表L中第i个数据元素之前插入数据元素e   

Status ListInsert_Sq(SqList &L,int i ,ElemType e)
{
   if(i<1 || i>L.length+1) return ERROR;             //i值不合法
   if(L.length==MAXSIZE) return ERROR;    //当前存储空间已满     
   for(j=L.length-1;j>=i-1;j--) 
       L.elem[j+1]=L.elem[j];    //插入位置及之后的元素后移
    L.elem[i-1]=e;                     //将新元素e放入第i个位置
    ++L.length;                 //表长增1
    return OK;
}

时间复杂度为O(n),空间复杂度为O(1),因为他没有占用任何的辅助空间

(4)删除:将线性表L中第i个数据元素删除   

Status ListDelete_Sq(SqList &L,int i)
{
   if((i<1)||(i>L.length)) return ERROR;     //i值不合法
   for (j=i;j<=L.length-1;j++)                   
    L.elem[j-1]=L.elem[j];       //被删除元素之后的元素前移  
   --L.length;                                    //表长减1
  return OK;
}

时间复杂度为O(n),空间复杂度为O(1),因为他没有占用任何的辅助空间

4、特点

利用数据元素的存储位置表示线性表中相邻数据元素之间的前后关系,即线性表的逻辑结构与存储结构一致
在访问线性表时,可以快速地计算出任何一个数据元素的存储地址。因此可以粗略地认为,访问每个元素所花时间相等(随机存取)

5、优缺点

(1)优点

  • 存储密度大(结点本身所占存储量/结点结构所占存储量),等于1
  • 可以随机存取表中任一元素

(2)缺点

  • 在插入、删除某一元素时,需要移动大量元素
  • 浪费存储空间,数组定义的偏大会浪费空间
  • 属于静态存储形式,数据元素的个数不能自由扩充,因为是采用数组来存储的不够灵活

总结:

1、相关函数

malloc函数:开辟m字节长度的地址空间,并返回值这段空间的首地址

sizeof函数:计算变量x的长度

free函数:释放指针p所指变量的存储空间,即彻底删除一个变量

2、参数的传递方式

(1)值传递

(2)传递地址

指针,形参与实参占用不同的内存单元,形参的值是实参的副本

数组作为参数传递的是首地址

(3)传递引用类型的参数

在内存中没有产生实参的副本,直接对实参进行操作。数据量较大时可以节省空间。

原文地址:https://www.cnblogs.com/zhai1997/p/13363954.html