👍数据结构——线性表(c)
文章目录
一、线性表的定义与特点(逻辑结构)
线性表:一个线性表是具有n个相同数据类型的数据元素的有限序列。
- 每个数据元素的具体含义:在不同的情况下各不相同,可以是一个数,一个符号,也可以是一页书,甚至其他更复杂的信息。
- 线性表中元素之间的关系:线性关系。
- 线性表的长度:线性表中元素的个数n(n>=0),n=0时,称为空表。
- 位序: a i \displaystyle a_i ai是第 i 个元素,称 i 为数据元素 a i \displaystyle a_i ai在线性表中的位序。
特点:
(1)表头元素:线性表存在唯一的一个被称作 “第一个” 的数据元素。
(2)表尾元素:存在唯一的一个被称作 “最后一个” 的数据元素。
(3)除第一个元素外,集合中的每个数据元素有且仅有一个直接前驱。
(4)除最后一个元素外,集合中的每个数据元素有且仅有一个直接后继。
二、线性表的顺序表示和实现(存储结构-顺序存储)
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。
一般用数组表示。
1.顺序表
- 特点:
(1)存储单元地址连续
(2)逻辑上相邻的数据元素其物理位置也相邻
(3)存储密度 100%
(4)随机存取 - 优点
(1)不需要额外的存储空间来表示元素之间的逻辑关系,存储密度高
(2)可以随机地存取表中的任意一个元素 - 缺点
(1)插入和删除元素时需要移动大量的元素
(2)必须事先进行空间分配,大片连续空间分配不方便,改变容量不方便
2.基本操作的实现
- 定义顺序表类型(采用动态分配方式)
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef struct{
int *elem; //存储空间基址1
int length; //当前长度
int listsize; //当前分配的存储容量
}SqList;
- 函数声明
void InitList_Sq(SqList *L); //线性表初始化
void DestroyList_Sq(SqList *L); //销毁线性表
void ClearList_Sq(SqList *L); //将L置为空表
bool ListEmpty_Sq(SqList L); //判断L是否为空
int ListLength_Sq(SqList L); //返回线性表L中数据元素的个数
int GetELem_Sq(SqList L, int i); //返回第i个数据元素的值
void ListInsert_Sq(SqList *L, int i, int a); //在i的位置插入元素
int ListDelete_Sq(SqList *L, int i); //删除线性表中第i个元素
void ListTraverse_Sq(SqList L); //线性表遍历
SqList* MergeList_Sq(SqList La, SqList Lb); //顺序表的合并算法
- 创建一个空的顺序表
//线性表初始化:创建一个空的顺序表
void InitList_Sq(SqList *L){
L->elem = (int *)malloc(LIST_INIT_SIZE*sizeof(int));
if(!L->elem){
printf("内存分配失败!");
return;
}
L->length = 0;
L->listsize = LIST_INIT_SIZE;
}
- 判断顺序表是否为空表
//判断L是否为空表
bool ListEmpty_Sq(SqList L){
if(L.length == 0){
return true;
}
else
return false;
}
- 返回线性表中数据元素的个数
//返回线性表L中数据元素的个数
int ListLength_Sq(SqList L){
return L.length;
}
- 返回线性表中第i个位置数据元素的值
//返回第i个数据元素的值
int GetELem(SqList L, int i){
if(i < 1 || i > L.length){
printf("越界!");
exit(0);
}
else{
return(L.elem[i-1]);
}
}
- 在顺序表第i个数据元素前插入元素a
//在i的位置插入元素a
void ListInsert_Sq(SqList *L, int i, int a){
int *newbase;
//判断i的范围是否有效
if(i < 1 || i > L->length+1){
printf("越界!");
return;
}
//判断当前存储空间是否已满,若已满,则重新申请一片更大的内存空间
if(L->length >= L->listsize){
newbase = (int *)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(int));
if(!newbase){
printf("内存分配失败!");
return;
}
L->elem = newbase;
L->listsize += LISTINCREMENT;
}
int *q = &(L->elem[i-1]);
int *p;
for(p = &(L->elem[L->length-1]); p>=q; --p){
*(p+1) = *p;
}
*q = a;
L->length++;
}
- 删除线性表中第i个元素并返回删除的元素的值
//删除线性表中第i个元素并返回删除的元素的值
int ListDelete_Sq(SqList *L, int i){
if( i < 1 || i > L->length ){
printf("越界!");
return 0;
}
int *p = &(L->elem[i-1]);
int e = *p;
int *q = L->elem + L->length-1;
for(++p; p <= q; ++p){
*(p-1) = *p;
}
--L->length;
return e;
}
- 顺序表的合并
//顺序表的合并算法
//已知顺序表La和Lb的元素是按值非递减排列
void MergeList_Sq(SqList La, SqList Lb, SqList *Lc){
int *pa, *pb, *pc, *pa_last, *pb_last;
pa = La.elem;
pb = Lb.elem;
Lc->listsize = Lc->length = La.length+Lb.length;
pc = Lc->elem = (int*)malloc(Lc->listsize*sizeof(int));
if(!Lc->elem){