一 概述
线性表的顺序存储又称作顺序表,它是一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。第1个元素存储在线性表的起始位置,第i个元素的存储位置后面紧接者存储的是第i+1个元素,称i为元素ai在线性表中的位序。因此,顺序表的特点是表中元素的逻辑顺序与其物理顺序相同。
二 顺序表与数组之间的关系
假设线性表L存储的起始位置为LOC(A),sizeof(ElemType)是每个元素所占用的内存空间的大小;
线性表所对应的顺序存储 |
注意:线性表中元素的位序是从1开始的,而数组中元素的下标是从0开始的。一维数组可以是静态分配的,也可以是动态分配的。
静态分配:在静态分配时,由于数组的大小和空间实现已经固定,一旦空间占满,再加入新的数据将会产生溢出,进而导致程序崩溃。
动态分配:在动态分配时,由于存储数组的空间是在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用以替换原来的存储空间,从而达到扩充存储数组空间的目的,而不需要为线性表一次性地划分所有空间。
注意:动态分配并不是链式存储,它同样属于顺序存储结构,物理结构没有变化,依然是随机存取方式,只是分配的空间大小可以在运行时决定。
三 顺序表的特点
顺序表最主要的特点是随机访问,即通过首地址和元素序号可在时间O(1)内找到指定的元素。
顺序表的存储密度高,每个结点只存储数据元素。
顺序表逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素。
顺序表在存储二叉树的时候,适合存储完全二叉树,按层序遍历。对于非完全二叉树,会存在空值元素。
四 顺序表的代码实现
代码头部分与宏定义:
#include<iostream>
using namespace std;
//宏定义
#define OK 1
#define ERROR 0
#define OVERFLOW 2
#define MAXSIZE 100 //顺序表可能达到的最大长度
数据类型重命名部分:
typedef int Status; //Status 是函数返回值类型,其值是函数结果状态码
typedef int ElemType; //ElemType 为可定义的数据类型,此处设置为int类型
typedef struct
{
ElemType *elem; //存储空间的基地址
int length; //顺序表的当前长度
}SqList; //可以作为类型声明新的结构体变量
初始化顺序表:
//初始化顺序表
Status InitList_Squeue(SqList &L) {
L.elem = new ElemType[MAXSIZE];
//C语言中,exit(1)表示异常退出,exit(0)表示正常退出。
/*exit是系统级别的调用,是一个函数,
*表示一个进程的结束。
*exit在调用处强行退出程序,运行依次就结束。
*/
if(!L.elem) exit(OVERFLOW); //存储分配失败
L.length = 0; //空表长度为0
/*return是语言级别的,是关键字,他表示调用堆栈的返回,
*return用于一个结束一个函数的执行,在一般函数中将函数
*的执行信息传给其他调用函数使用,如果是main函数则结束
*并退出程序。
*/
return OK;
}
顺序表的查找:
//顺序表的查找
int LocateElem_Squeue(SqList L, ElemType e){
for(int i; i < L.length; i++){
if(L.elem[i] == e)
return i+1; //顺序表中i+1表示是数组中第i个位置的数据在顺序表中的序列
return 0;
}
}
顺序表的插入:
//在顺序表L中第i个位置插入新的元素e,i的合法范围为1<= i <= L.length+1(插入)
//插入的过程中,增加一个数据位,需要移动数据时,先移动数据,然后将数据插入
Status ListInsert_Squeue(Sqlist &L, ElemType e){
if(i<1 || i>L.length + 1) return ERROR; //i值不合法
if(L.length == MAXSIZE) return ERROR; //当前存储空间已满,达到了数据表的最大值
for(int 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;
}
}
顺序表的删除:
/*顺序表在删除数据的时候,先删除某个数据然后将删除后的数据前移
*顺序表的删除
*在顺序表中L中删除第i个元素,并用e返回其值
*i值的合法范围是1<=i<=L.length
*/
Status ListDelete_Squeue(SqList &L, int i, ElemType &e) {
if(i<1 || i>L.length) return ERROR; //i值不合法
e = L.elem[i-1]; //将欲删除的元素保留在e中
for(int j=i;j <= L.length;j++) {
L.elem[j-1] = L.elem[j]; //被删除元素之后的元素前移
--L.length; //表长减1
return OK;
}
}