1.线性表
(1)定义:线性表是具有相同(每个数据元素所占空间一样大)数据类型的n(n>=0)个数据元素的有限序列,其中n为表长,当n=0时线性表是一个空表。若用L命名线性表,则其一般表示为:
L=(a1,a2,a3,...,ai,ai+1,...,an)
①ai是线性表中的“第i个”,元素线性表中的位序
②a1是表头元素,an是表尾元素
③除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后继
(2)线性表的基本操作
InitList(&L):初始化表。构造一个空的线性表L,分配内存空间。
DestroyList(&L):销毁操作。销毁线性表,并释放线性表L所占用的内存空间。
ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。
ListDelete(&L,i,&e):删除操作。删除表L中第i个位置的元素,并用e返回删除元素的值。
LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素。
GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值。
其他常用操作:
Length(L):求表长。返回线性表L的长度,即L中数据元素的个数。
PrintList(L):输出操作。按前后顺序输出线性表L的所有元素值。
Empty(L):判空操作。若L为空表,则返回true,否则返回false。
(3)对参数的修改结果需要“带回来”时,需要传入参数的引用“&”。
这是没有“带回来”的函数操作
#include<stdio.h>
void test(int x){
x=1024;
printf("test函数内部 x=%d\n",x);
}
int main(){
int x=1;
printf("调用test前 x=%d\n",x);
test(x);
printf("调用test后 x=%d\n",x);
}
/*输出
调用test前 x=1
test函数内部 x=1024
调用test后 x=1
*/
这是“带回来”的操作,"&引入"这种操作仅在C++中适用
#include<stdio.h>
void test(int & x){
x=1024;
printf("test函数内部 x=%d\n",x);
}
int main(){
int x=1;
printf("调用test前 x=%d\n",x);
test(x);
printf("调用test后 x=%d\n",x);
}
/*输出
调用test前 x=1
test函数内部 x=1024
调用test后 x=1024
*/
2.顺序表
(1)静态分配
定义:用顺序存储的方式实现线性表顺序存储。把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。
设线性表中第一个元素a1的存放位置为LOC(L),则a2的位置为LOC(L)+数据元素的大小,a3的位置为LOC(L)+2*数据元素的大小。
数据元素的大小由sizeof()函数求得,如sizeof(int) = 4B
#include<stdio.h>
#define MaxSize 10 //定义最大长度
typedef struct{
int data[MaxSize]; //用静态的“数组”存放数据元素
int length; //顺序表当前长度
}SqList; //顺序表的类型定义
//初始化一个顺序表
void InitList(SqList &L){
for(int i=0;i<MaxSize;i++)
L.data[i]=0; //将所有数据元素设置为默认初始值
L.length=0; //顺序表初始长度为0
}
int main(){
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//后续操作
return 0;
}
如果不初始化顺序表,顺序表存储空间中可能会有遗留的“脏数据”
顺序表的表长刚开始确定后就无法更改。
(2)动态分配
#define InitSize 10 //顺序表的初始长度
typedef struct{
ElemType *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SeqList; //顺序表的类型定义(动态分配方式)
C语言中可以用malloc函数申请动态内存,free释放内存空间。
malloc函数返回一个指针,需要强制转换为定义的数据元素类型指针。
L->data = (ElemType *)malloc(sizeof(ElemType)*InitSize);
#include<stdlib.h>
#define InitSize 10 //默认的最大长度
typedef struct{
int *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SeqList;
//顺序表初始化
void InitList(SeqList *L){
//用malloc函数申请一片连续的存储空间
L->data=(int *)malloc(InitSize*sizeof(int));
L->length=0;
L->MaxSize=InitSize;
}
//增加动态数组的长度
void IncreaseSize(SeqList *L,int len)
{
int *p=L->data; //定义指针p,使得p指针指向的位置与data指向的为一个位置
L->data=(int *)malloc((L->MaxSize+len)*sizeof(int)); //为data数据元素重新申请新的内存空间,新的内存空间长度增加
for(int i=0;i<L->length;i++){
L->data[i]=p[i]; //将数据复制到新区域
}
L->MaxSize=L->MaxSize+len; //顺序表最大长度增加len
free(p); //释放原来的内存空间
}
int main(){
SeqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//往顺序表里随便插入几个元素
IncreaseSize(L,5);
return 0;
}
(3)插入操作
//定义一个静态顺序表
#define MaxSize 10
typedef struct{
int data[MaxSize];
int length;
}SqList;
//插入操作
void ListInsert(SqList *L,int i,int e){
for(int j=L->length;j>i;j--)
L->data[j]=L->data[j-1];
L->data[i-1]=e;
L->length++;
}
int main(){
SqList L;
InitList(L);
//插入元素
ListInsert(L,3,3);
return 0;
}
但本插入代码缺少健壮性,将ListInsert函数更改成一个布尔型函数(C++实现)
bool ListInsert(SqList &L,int i,int e){
if(i<1||i>L.length+1) //判断i的范围是否有效
return false;
if(L.length>=MaxSize) //当前存储空间已满,不能插入
return false;
for(int j=L.length;j>=i;j--) //将第i个元素及其后的元素后移
L.data[j]=L.data[j-1];
L.data[i-1]=e; //在位置i处放入e
L.length++; //长度加1
return ture;
}
(4)删除操作
bool ListDelete (SqList &L,int i;int &e){
if(i<1||i>L.length)
return false;
e=L.data[i-1]; //将被删除的元素赋值给e
for(int j=i;j<L.length;j++)
L.data[j-1]=L.data[j];
L.length--; //线性表的长度减1
return true;
}
int main(){
SqList L;
InitList(L);
//插入元素
int e=-1; //用变量e把删除的元素“带回来”
if(ListDelete(L,3,e))
printf("已删除第3个元素,删除元素的值为=%d\n",e);
else
printf("位序i不合法,删除失败\n");
return 0;
}
(5)顺序表查找
GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值。
①静态内存
#define MaxSize 10
//定义一个静态表
typedef struct{
ElemType data[MaxSize];
int length;
}SqList;
ElemType GetElem(SqList L,int i){
return L.data[i-1];
}
②动态内存
#define InitSize 10
typedef struct{
ElemType *data; //指示动态分配数组的指针
int MaxSize;
int length;
}SeqList;
ElemType GetElem(SeqList L,int i){
return L.data[i-1];
}
LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素。
#define InitSize 10
typedef struct{
ElemType *data; //指示动态分配数组的指针
int MaxSize;
int length;
}SeqList;
//在顺序表L中查找第一个元素值等于e的元素,并返回其位序
int LocateElem(SeqList L,ElemType e){
for(int i=0;i<L.length;i++){
if(L.data[i]==e)
return i+1; //数组下标为i的元素值等于e,返回位序i+1
}
return 0; //退出循环,说明查找失败
}
注意:C语言中,结构体比较不能直接用“==”。