线性表的顺序存储结构的基本操作
头文件及宏定义
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define LIST_INIT_SIZE 100 //顺序表存储空间的初始分配量
#define LIST_INCREMENT 10 //顺序表存储空间的分配增量
#define MAXSIZE 100 //数组容量
typedef int Status;
typedef int ElemType;
typedef int Array[MAXSIZE];
线性表的动态分配顺序存储结构
/*
完整的顺序存储表三要素:基址,长度,分配的存储容量
*/
typedef struct{
ElemType* elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量
}SqList;
构造一个空的顺序表
为顺序表分配存储空间
Status InitList(SqList* L){
//动态内存分配
L = (ElemType* )malloc(sizeof(ElemType) * LIST_INIT_SIZE);
if(L == NULL){
return(OVERFLOW); //存储空间分配失败
}
L -> length = 0; //空表长度为0
L -> listsize = LIST_INIT_SIZE; //初始存储空间
}
初始化数组
初始化一个具有n个元素的数组
Status InitArray(Array A,int n){
if(A == NULL || n == 0){
return ERROR;
}
int i = 0;
A[i++] = 0; //索引为0位置存放数组长度
while(i <= n){
int temp;
scanf("%d",&temp);
A[i++] = temp;
A[0]++; //长度加1
}
return OK;
}
构建一个顺序表
将数组中的数据依次填入顺序表
前提条件:数组不为空
注:数组中数据A[0]储存元素长度,填入数据从A[I]开始
Status InitializeList(SqList* L, Array A){
if(A == NULL){
return ERROR;
}
int i = 0; //索引
while(i < A[0]){
L -> elem[i] = A[i + 1];
L -> length++; //顺序表长度加1
i++;
}
return OK;
}
销毁顺序表L
释放顺序表L所占的内存空间
前提条件:顺序表L已存在
Status DestoryList(SqList* L){
if(L == NULL || L -> elem == NULL){
return ERROR;
}
free(L -> elem); //释放顺序表所占空间
/*
free(L -> elem)释放分配给指针L -> elem的动态空间,
但L -> elem不会自动变成空指针,需要手动置空
*/
L -> elem = NULL; //置空
L -> length = 0; //元素长度归0
L -> listsize = 0; //存储容量归0
return OK;
}
置空顺序表
只是清除线性表中的数据,顺序表所占空间不释放
前提条件: 顺序表L已存在
Status ClearList(SqList* L){
if(L == NULL || L -> elem == NULL){
return ERROR;
}
L -> length = 0;
return OK;
}
判空
如果顺序表L不为空返回TRUE,否则返回FALSE
前提条件:顺序表L已存在
Status ListEmpty(SqList L){
if(L.elem == NULL){
return ERROR;
}
return L.length == 0 ? FALSE : TRUE;
}
顺序表长度
返回顺序表长度,即数据元素个数
前提条件:顺序表L已存在
int ListLength(SqList L){
if(L.elem == NULL){
return ERROR;
}
return L -> length ;
}
取值
获得顺序表中索引为 i 的元素的取值,用e返回
前提条件:
- 顺序表L已存在
- 0 <= i <= ListLength(L) - 1
Status GetElem(SqList L, int i, ElemType* e){
if(L.elem == NULL){
return ERROR;
}
if(i < 0 || i > L.length - 1){
return ERROR;
}
*e = L.elem[i];
return OK;
}
查找
返回顺序表L中第1个与e满足相等关系的数据元素的索引,若不存在,则返回0
前提条件:顺序表L已存在
int LocatElem(SqList L, ElemType e){
if(L.elem == NULL){
return ERROR;
}
int i = 0; //i为索引,从0开始
ElemType* p = L.elem;
for(i <= L.length - 1 && *p++ != e)){
++i;
}
if(i <= L.length - 1){
return i;
}else{
return 0;
}
}
查找元素前驱
获取数据元素cur_e(不是第一个数据元素)的前驱将其储存在pre_e中
前提条件:线性表L已存在且至少包含2个数据元素
Status PrioElem(SqList L, ElemType cur_e, ElemType* pre_e){
if(L.elem == NULL){
return ERROR;
}
if(L.length < 2){
return ERROR;
}
int i = 0; //i为索引,从0开始
while(i <= L.length - 1 && L.elem[i] != cur_e){
++i;
}
//cur_e是首个数据元素或者没有找到cur_e
if(i == 0 || i > L.length - 1){
return ERROR;
}
*pre_e = L.elem[i - 1];
return OK;
}
查找元素后继
获取数据元素cur_e(不是最后一个数据与元素)的后继将其存储在next_e中
前提条件:线性表L已存在且至少包含2个数据元素
Status NextElem(SqList L, ElemType cur_e, ElemType* next_e){
if(L.elem == NULL || L.length < 2){
return ERROR;
}
int i = 0;
while(i <= L.length - 1 && L.elem[i] != cur_e){
++i;
}
//cur_e是最后一个数据元素或者没有找到cur_e
if(i == L.length - 1 || i >= L.length){
return ERROR;
}
*next_e = L.elem[i + 1];
return OK;
}
插入
向线性表索引为i的位置插入e
前提条件:
- 线性表L已存在
- 0 <= i <= L.length - 1
Status ListInsert(SqList* L, int i, ElemType e){
if(L == NULL || L -> elem == NULL){
return ERROR;
}
//i是否合理
if(i < 0 || i > L -> length - 1){
return ERROR;
}
ElemType* newbase;
ElemType* p, * q;
//初始存储空间已满,增加分配
if(L -> length >= L -> listsize){
newbase = (ElemType* )realloc(L -> elem, (L -> listsize + LISTINCREMENT) * sizeof(ElemType));
if(newbase == NULL){
exit(OVERFLOW);
}
L -> elem = newbase; //新基址
L -> listsize += LISTINCREMENT; //增加后的存储容量
}
q = &(L -> elem[i]); //q为插入位置
//插入位置及之后的元素后移
for(p = &(L -> elem[L -> length -1]); p >= q ; --p ){
*(p + 1) = *p;
}
//元素e插入
*q = e;
//表长加1
L -> length++;
return OK;
}
删除
删除线性表索引为i位置的数据元素并用e返回其值
前提条件:
- 线性表L已存在
- 0 <= i <= L.length - 1
Status ListDelete(SqList* L, int i, ElemType* e){
if(L == NULL || L -> elem == NULL){
return ERROR;
}
//i是否合理
if(i < 0 || i > (L -> length -1)){
return ERROR;
}
ElemType* p,* q;
//用e返回其值
*e = L -> elem[i];
//q为删除位置
q = &(L -> elem[i]);
for(p = &(L -> elem[L -> length - 1]); q <= p; q++){
*q = *(q + 1);
}
//表长减1
L -> length--;
return OK;
}
打印线性表元素
前提条件:线性表已存在
Status ListTraverse(SqList L){
if(L.elem == NULL){
return ERROR;
}
int i; //索引
for(i = 0; i < L.length; i++){
printf("L.elem[%d] = %d ", i, L.elem[i]);
}
return OK;
}
测试代码
int main(void){
SqList L;
Array A;
int length, n; //n为数组元素个数
ElemType e, temp;
int i = 0; //索引
printf("Number of input array elements n :");
scanf("%d", &n);
//初始化数组
printf("Please enter n values :");
InitArray(A,n);
//构造一个空的顺序表
InitList_Sq(&L);
//构建顺序表
InitializeList(&L, A);
//遍历构建后的顺序表
printf("\n");
ListTraverse(L);
printf("\n");
//判空
if(ListEmpty(L)){
printf("L is empty\n");
}else{
printf("L is not empty\n");
}
//返回元素长度
length = ListLength(L);
printf("The length of L is %d\n", length);
//取值(此处的3是索引,对应顺序表第四个位置)
if(GetElem(L, 3, &e)){
printf("The data element with index 3 in L is %d\n", e);
}else{
printf("No results found!\n");
}
//定位
i = LocateElem(L,6);
if(i != 0){
printf("The data element of index equal to 6 in L is %d\n", i);
}else{
printf("There is no data element equal to 6 in L!\n");
}
//前驱
temp = L.elem[2];
if(PriorElem(L,temp, &e)){
printf("The precursor of temp(L.elem[2]) is %d\n", e);
}else{
printf("No results fount!\n");
}
//后继
temp = L.elem[3];
if(NextElem(L, temp, &e)){
printf("The next of temp(L.elem[3]) is %d\n", e);
}else{
printf("No results fount!\n");
}
//插入
temp = 100;
ListInsert(&L,2,temp);
printf("Traversal results after inserting element:\n");
ListTraverse(L);
printf("\n");
//插入后查找L.elem[3]的后继
temp = L.elem[3];
if(NextElem(L, temp, &e)){
printf("The next of temp(L.elem[3]) is %d\n", e);
}else{
printf("No results fount!\n");
}
//删除
ListDelete(&L, 3, &e);
printf("Traversal results after deleteing element:\n");
ListTraverse(L);
printf("\n");
printf("The deleted element data is %d",e);
return 0;
}
测试结果