赞
踩
秋风阁——北溪入江流:https://focus-wind.com/
秋风阁——数据结构-线性表
线性表(Linear List):是具有相同数据类型的
n
(
n
≥
0
)
n(n \geq 0)
n(n≥0)个数据元素的有限序列。线性表的结构是逻辑结构中的线性结构。一般表示为:
L
=
(
a
1
,
a
2
,
⋯
,
a
i
,
a
i
+
1
,
⋯
,
a
n
)
(
n
≥
0
)
L = (a_1, a_2, \cdots, a_i, a_{i + 1}, \cdots, a_n) (n \geq 0)
L=(a1,a2,⋯,ai,ai+1,⋯,an)(n≥0)
线性表中元素具有相同的数据类型,即各元素所占空间大小相同。
线性表是 n ( n ≥ 0 ) n(n \geq 0) n(n≥0)个元素的有限序列。说明线性表中元素个数有限,元素之间有序。(元素之间有序指的是线性表中的各元素之间有先后次序,不是其值有先后次序,注意理解元素和值的区别)
上述操作中参数中"&"表示C++中的引用传递,在C语言中采用指针可以达到同样的效果。在C/C++中,需要使用传入传出参数时,可以使用引用传递或地址传递等方式进行传值操作。
顺序表:线性表的顺序存储又称顺序表。使用一组地址连续的存储单元依次存储线性表中的数据元素。
高级程序设计语言中通常采用数组描述顺序表。
注意:线性表中元素的位序是从1开始的,数组元素的下标是从0开始的。
一般来说,线性表的第
i
i
i个元素
a
i
a_i
ai的存储位置为:
L
o
c
(
a
i
)
=
L
o
c
(
a
1
)
+
(
i
−
1
)
×
S
i
z
e
o
f
(
D
a
t
a
T
y
p
e
)
1
≤
i
≤
n
Loc(a_i) = Loc(a_1) + (i - 1) \times Sizeof(DataType) \qquad 1 \leq i \leq n
Loc(ai)=Loc(a1)+(i−1)×Sizeof(DataType)1≤i≤n
假设线性表 L L L的存储结构为LOC(A),线性表的数据元素类型为ElemType,Sizeof(ElemType)是每个数据元素所占存储空间的大小,则表L对应的存储结构如下图所示:
在创建顺序表时,可以通过静态分配和动态分配创建顺序表。
在创建顺序表时,顺序表容量一经确定,不可以再更改。
// 静态分配顺序表的最大长度
#define MaxSize 50
typedef struct {
// 顺序表的数据元素
DataType data[MaxSize];
// 顺序表的当前长度
int length;
} SequeenList;
注意顺序表中length和MaxSize的区别,MaxSize指的是顺序表理论最大元素个数,length指顺序表当前长度个数
动态分配,存储数组的空间在程序执行过程中通过动态存储分配语句分配的,数据空间存满,可以另外开辟一块更大的空间来替换原来的存储空间,达到扩容的目的,从而不需要一次性地分配所有空间。
动态分配依旧是顺序存储结构,不是链式存储结构,只是分配的空间大小可以在运行时动态决定。
// 顺序表的初始化长度
#define InitSize 100
typedef struct {
// 动态数组指针
DataType *data;
// 顺序表的当前长度
int lenght;
// 数组最大容量,动态分配的最大长度是不确定的,所以相比于静态分配,需要额外的参数来存储数组最大容量值
int MaxSize;
} SequeenList;
C语言动态分配语句:
L.data = (DataType *)malloc(sizeof(DataType) * InitSize;
malloc函数:动态申请内存空间
会申请连续的一整片的内存空间,malloc函数返回一个指针,需强制转换成定义的数据元素类型指针。
free函数:动态释放内存空间
释放对应的内存空间,与malloc函数成对出现。在不需要内存空间时,请主动释放对应的内存空间,减少系统资源的占用
顺序表的主要特点有:
静态分配顺序表的主要特点:
动态分配顺序表的主要特点:
这里仅讨论顺序表的动态分配表上的基本操作,静态分配表的操作和动态分配表大同小异。
// 动态分配顺序表
typedef struct {
DataType *data;
int length;
int MaxSize;
} SequenceList;
在下列操作中,若函数定义参数需要在外部使用,则需使用传入传出参数,通过指针*
来进行地址传递,在调用函数时,或变量为普通变量,不是指针变量,则需要在参数中使用&
来进行取地址操作。
下列实现中,若无特别说明,以int的返回值作为函数是否执行成功的标志。0:执行失败,非0:执行成功。
为数据元素分配内存空间,并初始化顺序表长度和最大值。
/**
* 初始化顺序表
* @param L 需要初始化的顺序表
* @param initLength 顺序表初始化长度
* @return
*/
int InitSequenceList(SequenceList *L, int initLength) {
// 动态分配顺序表存储空间
L->data = (DataType *) malloc(sizeof(DataType) * initLength);
// 初始化顺序表参数
L->length = 0;
L->MaxSize = initLength;
return 1;
}
/**
* 插入操作
* @param L 需要执行插入的顺序表
* @param i 位序(i <= i <= length + 1)
* @param data 插入元素
* @return
*/
int SequenceListInsert(SequenceList *L, int i, DataType data) {
if (i < 1 || i > L->length + 1) {
// 插入位置非法:i <= i <= length + 1(i为顺序表位序)
printf("Error:Illegal insertion position!\n");
return 0;
} else if (L->length >= L->MaxSize) {
// 顺序表溢出,顺序表最大长度为MaxSize,超过MaxSize,则会产生溢出错误
printf("Error:Sequence list overflow!");
return 0;
} else {
// 可以进行正常插入操作
// 从i开始的所有元素后移一位
for (int j = L->length; j >= i; j--) {
L->data[j] = L->data[j - 1];
}
// 在位置i处放入插入元素
L->data[i - 1] = data;
// 顺序表长度加1,注意该语句,不可省略
L->length++;
return 1;
}
}
后移:int j = L->length; j >= i; j–
/**
* 删除操作
* @param L 需要执行插入的顺序表
* @param i 位序(i <= i <= length)
* @param data 传入传出参数,用于接收删除元素的值
* @return
*/
int SequenceListDelete(SequenceList *L, int i, DataType *data) {
if (i < 1 || i > L->length) {
// 删除位置非法:i <= i <= length(i为顺序表位序)
printf("Error:Illegal delete position!\n");
return 0;
} else {
// 可以进行正常删除操作
// 将删除元素的值传出给data
*data = L->data[i - 1];
// 从i + 1开始后的所有元素前移一位
for (int j = i; j < L->length; j++) {
L->data[j - 1] = L->data[j];
}
L->length--;
return 1;
}
}
前移:int j = i; j < L->length; j++
/**
* 按位序查找
* @param L 需要执行查找的顺序表
* @param i 位序(i <= i <= length)
* @param data 传入传出参数,用于接收查找到的值
* @return
*/
int SequenceListGet(SequenceList *L, int i, DataType *data) {
if (i < 1 || i > L->length) {
// 获取元素位置非法:i <= i <= length(i为顺序表位序)
printf("Error:Illegal get data position!\n");
return 0;
} else {
*data = L->data[i - 1];
return 1;
}
}
/**
* 按值查找
* @param L 需要执行查找的顺序表
* @param data 需要比较的元素
* @return 位序,0:未查找到该元素
*/
int SequenceListLocate(SequenceList *L, DataType data) {
for (int i = 0; i < L->length; i++) {
if (L->data[i] == data) {
// 这里的i为数组下标,需转换为位序值
return i + 1;
}
}
return 0;
}
/**
* 销毁顺序表
* @param L 需要销毁的顺序表
* @return
*/
int DestroySequenceList(SequenceList *L) {
L->length = 0;
L->MaxSize = 0;
// 释放申请的空间
free(L->data);
L->data = NULL;
return 1;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。