线性表——顺序表部分知识归纳及动态存储中各接口的实现(C语言)

线性表:

  线性表是最基本、最简单、也是最常用的一种数据结构。一个线性表是N个具有相同特性的数据元素的有限序列,在实际中广泛使用。
  线性表在逻辑上是线性结构,也就说是连续的一条直线,但是在物理结构上并不一定是连续的,在物理结构上存储时,通常以数组和链式结构的形式进行存储。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。
  常见的线性表有顺序表、链表、栈、队列、字符串等。
在这里插入图片描述

顺序表:

  顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。

顺序表分为:
  1. 静态顺序表:使用定长的数组进行存储
    在这里插入图片描述
// 顺序表的静态存储
#define N 4
typedef int SLDataType;
typedef struct SeqList
{
   SLDataType array[N]; // 定长数组
   size_t size; // 有效数据的个数
}SeqList;
  1. 动态顺序表:使用动态开辟的数组进行存储
    在这里插入图片描述
// 顺序表的动态存储
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个接口进行实现:

  1. 初始化
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);
}
  1. 销毁
void SeqListDestory(SeqList* psl); //销毁
{
	assert(psl);
	free(psl->array);
	psl->size = 0;
	psl->capacity = 0;
}
  1. 扩容
void CheckCapacity(SeqList* psl); //扩容
{
	assert(psl);
	if (psl->size == psl->capacity)
	{
		psl->capacity *= 2;
		realloc(psl->array, sizeof(SLDataType)* psl->capacity);
	}
}
  1. 尾插
void SeqListPushBack(SeqList* psl, SLDataType x); //尾插
{
	assert(psl);
	CheckCapacity(psl);
	psl->array[psl->size] = x;
	psl->size++;
}
  1. 尾删
void SeqListPopBack(SeqList* psl); //尾删
{
	assert(psl);
	assert(psl->size > 0);
	psl->size--;
}
  1. 头插
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++;
}
  1. 头删
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--;
}
  1. 查找
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;
}
  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++;
}
  1. 定点删除
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--;
}
  1. 删除指定数
void SeqListRemove(SeqList* psl, SLDataType x); //删除指定数
{
	assert(psl);
	int pos = SeqListFind(psl, x);
	if (pos != -1)
	{
		SeqListErase(psl, pos);
	}
}
  1. 修改
void SeqListModify(SeqList* psl, size_t pos, SLDataType x); //修改
{
	assert(psl);
	assert((pos >= 0) && (pos < psl->size));
	psl->array[pos] = x;
}
  1. 打印
void SeqListPrint(SeqList* psl); //打印
{
	assert(psl);
	for (int i = 0; i < psl->size; i++)
	{
		printf("%d ", psl->array[i]);
	}
	printf("\n");
}
  1. 冒泡排序
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;
		}
	}
}
  1. 二分查找
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;
}
  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);
		}
	}
}
下篇将更新线性表——链表部分知识归纳!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值