线性表是数据结构中最基本的一种数据结构,它是由同类型的n个数据元素组成的有限序列。线性表的顺序表示是将线性表中的元素存储在一段连续的存储空间中,称为顺序存储结构,也称为数组表示。
在顺序存储结构中,线性表中的元素在内存中是连续存储的。线性表的基本操作(如插入、删除、查找)可以通过对元素在数组中的位置进行操作来实现。一般情况下,我们将线性表中的第一个元素存储在数组下标为0的位置,第二个元素存储在下标为1的位置,以此类推,最后一个元素存储在下标为n-1的位置。
顺序存储结构的优点是可以随机访问任意一个元素,因此查找元素的时间复杂度为O(1);缺点是插入或删除一个元素时,需要移动后面的元素,因此时间复杂度为O(n)。此外,如果线性表长度变化比较频繁,会导致存储空间的浪费或不足。
下面我们将会实现线性表的初始化操作,插入或者删除元素,两个线性表的合并,代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define ElemType int
/*
elem是指向数组第一个元素的指针
length是当前的表长
listsize是当前分配的存储容量
*/
typedef struct {
ElemType* elem;
int length;
int listsize;
}SqList;
bool InitList_Sq(SqList* L);
bool ListInsert_Sq(SqList* L, int i, ElemType e);
bool ListDelete_Sq(SqList* L, int i, ElemType* e);
void PrintList(SqList L);
int Locate_Elem_Sq(SqList* L, ElemType e, bool (*compare)(ElemType, ElemType));
bool compare(ElemType i, ElemType j);
void MergeList_Sq(SqList La, SqList Lb, SqList* Lc);
int main(void) {
SqList La = { (ElemType[]) { 1, 3, 5, 7, 9 }, 5, LIST_INIT_SIZE };
SqList Lb = { (ElemType[]) { 2, 4, 6, 8, 10 }, 5, LIST_INIT_SIZE };
SqList Lc = { NULL, 0, LIST_INIT_SIZE };
MergeList_Sq(La, Lb, &Lc);
PrintList(La);
PrintList(Lb);
PrintList(Lc);
return 0;
}
/// @brief 初始化空的顺序表
/// @param L
/// @return 如果初始化成功则返回true
bool InitList_Sq(SqList* L) {
L->elem = (ElemType*) malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!L->elem) { return false; }
L->length = 0;
L->listsize = LIST_INIT_SIZE;
return true;
}
/// @brief 在顺序表第i个元素之前插入元素e
/// @param L 需要插入的表的地址
/// @param i 第i个元素
/// @param e 需要插入的元素e
/// @return 如果插入成功则返回true
bool ListInsert_Sq(SqList* L, int i, ElemType e) {
/*判断i是否合法*/
if (i < 1 || i > L->length) { return false; }
/*判断表是否已满*/
if (L->length == L->listsize) {
ElemType* newbase = (ElemType*) realloc(L->elem, L->listsize + LISTINCREMENT);
if (!newbase) { return false; }
L->elem = newbase;
L->listsize = L->listsize + LISTINCREMENT;
}
for (int j = L->length + 1; j > i; j--) {
L->elem[j - 1] = L->elem[j - 2];
}
L->elem[i - 1] = e;
L->length++;
return true;
}
/// @brief 删除表中的第i个元素,并用e返回其值
/// @param L 需要删除的表的地址
/// @param i 需要删除的元素的序号
/// @param e 被删除元素的地址
/// @return 如果删除成功则返回true
bool ListDelete_Sq(SqList* L, int i, ElemType* e) {
/*判断i的合法性*/
if (i < 1 || i > L->length) { return false; }
*e = L->elem[i - 1];
for (int j = i; j < L->length; j++) {
L->elem[j - 1] = L->elem[j];
}
L->length--;
return true;
}
void PrintList(SqList L) {
printf("[");
for (int i = 0; i < L.length; i++) {
printf("%d", L.elem[i]);
if (i != L.length - 1) {
printf(", ");
}
}
printf("]\n");
}
/// @brief 找到顺序表中与e相等的元素的位序
/// @param L 顺序表的地址
/// @param e 被比较的元素e
/// @param compare 比较函数
/// @return 如果找到则返回位序,如果没有找到则返回-1
int Locate_Elem_Sq(SqList* L, ElemType e, bool (*compare)(ElemType, ElemType)) {
for (int i = 0; i < L->length; i++) {
if ((*compare)(L->elem[i], e)) { return i + 1; }
}
return -1;
}
/// @brief 比较函数
/// @param i
/// @param j
/// @return 如果相等则返回true, 如果不相等则返回false
bool compare(ElemType i, ElemType j) {
if (i == j) { return true; }
return false;
}
/// @brief 将La,Lb合并到Lc中
/// @param La
/// @param Lb
/// @param Lc
void MergeList_Sq(SqList La, SqList Lb, SqList* Lc) {
Lc->elem = (ElemType*) malloc((La.length + Lb.length) * sizeof(ElemType));
if (!Lc->elem) { exit(1); }
Lc->length = La.length + Lb.length;
Lc->listsize = La.length + Lb.length;
ElemType* pa = &La.elem[0]; //指向La中的第一个元素
ElemType* pb = &Lb.elem[0]; //指向Lb中的第一个元素
ElemType* pc = Lc->elem; // 指向Lc中的第一个元素
ElemType* pa_last = La.elem + La.length - 1; // 指向 La 最后一个元素
ElemType* pb_last = Lb.elem + Lb.length - 1; // 指向 Lb 最后一个元素
while (pa <= pa_last && pb <= pb_last){
if (*pa <= *pb) {
*pc++ = *pa++;
} else {
*pc++ = *pb++;
}
}
while (pa <= pa_last) {
*pc++ = *pa++;
}
while (pb <= pb_last) {
*pc++ = *pb++;
}
}