线性表是最基本、最简单、也是最常用的一种数据结构。一个线性表是N个具有相同特性的数据元素的有限序列,在实际中广泛使用。
线性表在逻辑上是线性结构,也就说是连续的一条直线,但是在物理结构上并不一定是连续的,在物理结构上存储时,通常以数组和链式结构的形式进行存储。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。
常见的线性表有顺序表、链表、栈、队列、字符串等。
顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
// 顺序表的静态存储
#define N 4
typedef int SLDataType;
typedef struct SeqList
{
SLDataType array[N]; // 定长数组
size_t size; // 有效数据的个数
}SeqList;
// 顺序表的动态存储
typedef struct SeqList
{
SLDataType* array; // 指向动态开辟的数组
size_t size ; // 有效数据个数
size_t capacity ; // 容量空间的大小
}SeqList;
由于静态顺序表只适用于已经确定知道需要存多少个数据的场景,所以如果静态顺序表中N的设置过大,则会导致空间浪费,N的设置过小,则会导致空间不够两种情况,所以实际中我们更多使用的是动态顺序表,根据需要动态的来分配空间大小,所以下面仅对顺序表的动态存储进行实现。
我们主要实现以下16个接口(基本+拓展+延伸):
// 基本增删查改接口
1. void SeqListInit(SeqList* psl, size_t capacity); //初始化
2. void SeqListDestory(SeqList* psl); //销毁
3. void CheckCapacity(SeqList* psl); //扩容
4. void SeqListPushBack(SeqList* psl, SLDataType x); //尾插
5. void SeqListPopBack(SeqList* psl); //尾删
6. void SeqListPushFront(SeqList* psl, SLDataType x); //头插
7. void SeqListPopFront(SeqList* psl); //头删
8. int SeqListFind(SeqList* psl, SLDataType x); //查找
9. void SeqListInsert(SeqList* psl, size_t pos, SLDataType x); //定点插入
10. void SeqListErase(SeqList* psl, size_t pos); //定点删除
11. void SeqListRemove(SeqList* psl, SLDataType x); //删除指定数
12. void SeqListModify(SeqList* psl, size_t pos, SLDataType x); //修改
13. void SeqListPrint(SeqList* psl); //打印
// 扩展面试题实现
14. void SeqListBubbleSort(SeqList* psl); //冒泡排序
15. int SeqListBinaryFind(SeqList* psl, SLDataType x); //二分查找
// 本题要求:时间复杂度:O(N) 空间复杂度 O(1)
16. void SeqListRemoveAll(SeqList* psl, SLDataType x); //删除所有指定数
下面我们分别对这16个接口进行实现:
void SeqListInit(SeqList* psl, size_t capacity); //初始化
{
assert(psl);
assert(capacity != 0);
psl->capacity = capacity;
psl->array = (SLDataType *)malloc(sizeof(SLDataType) * psl->capacity);
psl->size = 0;
assert(psl->array);
}
void SeqListDestory(SeqList* psl); //销毁
{
assert(psl);
free(psl->array);
psl->size = 0;
psl->capacity = 0;
}
void CheckCapacity(SeqList* psl); //扩容
{
assert(psl);
if (psl->size == psl->capacity)
{
psl->capacity *= 2;
realloc(psl->array, sizeof(SLDataType)* psl->capacity);
}
}
void SeqListPushBack(SeqList* psl, SLDataType x); //尾插
{
assert(psl);
CheckCapacity(psl);
psl->array[psl->size] = x;
psl->size++;
}
void SeqListPopBack(SeqList* psl); //尾删
{
assert(psl);
assert(psl->size > 0);
psl->size--;
}
void SeqListPushFront(SeqList* psl, SLDataType x); //头插
{
assert(psl);
CheckCapacity(psl);
for (int i = psl->size; i > 0; i--)
{
psl->array[i] = psl->array[i - 1];
}
psl->array[0] = x;
psl->size++;
}
void SeqListPopFront(SeqList* psl); //头删
{
assert(psl);
assert(psl->size > 0);
for (int i = 1; i < psl->size; i++)
{
psl->array[i - 1] = psl->array[i];
}
psl->size--;
}
int SeqListFind(SeqList* psl, SLDataType x); //查找
{
assert(psl);
for (int i = 0; i < psl->size; i++)
{
if (psl->array[i] == x)
{
return i;
}
}
return -1;
}
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x); //定点插入
{
assert(psl);
assert((pos >= 0) && (pos <= psl->size));
CheckCapacity(psl);
for (int i = psl->size; i>pos; i--)
{
psl->array[i] = psl->array[i - 1];
}
psl->array[pos] = x;
psl->size++;
}
void SeqListErase(SeqList* psl, size_t pos); //定点删除
{
assert(psl);
assert((pos >= 0) && (pos < psl->size));
for (int i = pos + 1; i < psl->size; i++)
{
psl->array[i - 1] = psl->array[i];
}
psl->size--;
}
void SeqListRemove(SeqList* psl, SLDataType x); //删除指定数
{
assert(psl);
int pos = SeqListFind(psl, x);
if (pos != -1)
{
SeqListErase(psl, pos);
}
}
void SeqListModify(SeqList* psl, size_t pos, SLDataType x); //修改
{
assert(psl);
assert((pos >= 0) && (pos < psl->size));
psl->array[pos] = x;
}
void SeqListPrint(SeqList* psl); //打印
{
assert(psl);
for (int i = 0; i < psl->size; i++)
{
printf("%d ", psl->array[i]);
}
printf("\n");
}
void SeqListBubbleSort(SeqList* psl); //冒泡排序
{
assert(psl);
for (int i = 1; i < psl->size; i++)
{
int out = 1;
for (int j = 0; j < psl->size - i; j++)
{
if (psl->array[j] > psl->array[j + 1])
{
int t = psl->array[j];
psl->array[j] = psl->array[j + 1];
psl->array[j + 1] = t;
out = 0;
}
}
if (out == 1)
{
return;
}
}
}
int SeqListBinaryFind(SeqList* psl, SLDataType x); //二分查找
{
assert(psl);
int left = 0;
int right = psl->size - 1;
int mid;
while (left <= right)
{
mid = (right - left) / 2 + left;
if (x < psl->array[mid])
{
right = mid - 1;
}
else if (x > psl->array[mid])
{
left = mid + 1;
}
else
return mid;
}
return -1;
}
void SeqListRemoveAll(SeqList* psl, SLDataType x); //
{
assert(psl);
for (int i = 0; i < psl->size; i++)
{
if (psl->array[i] == x)
{
SeqListErase(psl, i);
}
}
}