【数据结构】顺序表

线性表是n个具有相同特性的数据元素的有限序列,包括顺序表、链表、栈、队列等。
线性表在逻辑结构上是连续的,但是在物理结构上不一定连续。

顺序表

顺序表的特点是:物理地址连续
通常采用数组存储,可分为:

  • 静态顺序表:使用定长数组存储
  • 动态顺序表:使用动态数组存储

既然顺序表的物理地址是连续的,那么就可以计算出某个元素的物理地址.
下图给出的即为计算物理地址的公式
在这里插入图片描述
顺序表的优点

  • 存储密度大,空间利用率高
  • 存储空间连续,允许元素随机访问(即查找元素方便)

顺序表的缺点

  • 长度固定,实现插入和删除操作不方便

顺序表的基本操作接口

typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* array; // 指向动态开辟的数组
	size_t size; // 有效数据个数
	size_t capicity; // 容量空间的大小
}SeqList;

void SeqListInit(SeqList* psl, size_t capacity);//初始化
void SeqListDestory(SeqList* psl);//销毁释放
void CheckCapacity(SeqList* psl);//检查存储元素是否达到上限
void SeqListPushBack(SeqList* psl, SLDataType x);//尾插法
void SeqListPopBack(SeqList* psl);//尾删法
void SeqListPushFront(SeqList* psl, SLDataType x);//头插法
void SeqListPopFront(SeqList* psl);//头删法
int SeqListFind(SeqList* psl, SLDataType x);//查找某元素所在位置
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);//在某个位置插入一个元素
void SeqListErase(SeqList* psl, size_t pos);//删除某位置的元素
void SeqListRemove(SeqList* psl, SLDataType x);//删除某个值的元素
void SeqListModify(SeqList* psl, size_t pos, SLDataType x);//修个某个位置元素的值
void SeqListPrint(SeqList* psl);//打印顺序表中的元素
void SeqListBubbleSort(SeqList* psl);//冒泡排序
int SeqListBinaryFind(SeqList* psl, SLDataType x);//二分查找

各接口的具体实现

#include"SeqList.h"

//初始化
void SeqListInit(SeqList* psl, size_t capacity)
{
	assert(psl);//判空

	psl->capicity = capacity;
	psl->array = (SLDataType *)malloc(capacity * sizeof(SLDataType));//开辟动态空间

	psl->size = 0;
}

void SeqListDestory(SeqList* psl)
{
	assert(psl);

	if (psl->array)
	{
		free(psl->array);//将一个数组free后,需要将其置空(NULL)
		psl->array = NULL;
		psl->capicity = 0;//并将其开辟的空间均置为0
		psl->size = 0;
	}
}

//检查是否到达上限
void CheckCapacity(SeqList* psl)
{
	assert(psl);

	if (psl->size == psl->capicity)
	{
		psl->capicity *= 2;
		psl->array = (SLDataType *)realloc(psl->array, psl->capicity * sizeof(SLDataType));
	}
}

//尾插法
void SeqListPushBack(SeqList* psl, SLDataType x)
{
	assert(psl);

	//插入一个元素需要检查是否需要进行扩容,
	//若psl->size == psl->capacity,则需要扩容
	CheckCapacity(psl);

	//尾插法即将要插入放入元素直接插到顺序表的末端,再将顺序表的大小加一
	psl->array[psl->size] = x;
	psl->size++;
}

//尾删法
void SeqListPopBack(SeqList* psl)
{
	assert(psl || psl->size);

	//直接将顺序表中有效元素的个数减一,即可删掉表中最后一个元素
	psl->size--;
}

//头插法
void SeqListPushFront(SeqList* psl, SLDataType x)
{
	assert(psl);

	//头插法是将每个元素向后移动一位,即将后面的那个元素覆盖
	//再将要插入的元素赋值给表中的第一个元素,表的长度加一
	for (int i = psl->size - 1; i >= 0; i++)
	{
		psl->array[i + 1] = psl->array[i];
	}
	psl->array[0] = x;
	psl->size++;
}

//头删法
void SeqListPopFront(SeqList* psl)
{
	assert(psl || psl->size);

	psl->size--;//先将表的长度减一
	//头删法是将后面的一个元素向前移动,即后面的元素将前面的元素覆盖
	for (int i = 0; i < psl->size; i++)
	{
		psl->array[i] = psl->array[i + 1];
	}

}

//查找该元素是否在顺序表中存在
int SeqListFind(SeqList* psl, SLDataType x)
{
	assert(psl);

	for (int i = 0; i < psl->size; i++)
	{
		if (psl->array[i] == x)//判断顺序表中元素的值与该值相等,返回顺序表中的位置
		{
			return i;
		}
	}
}

//在pos后插入一个元素
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x)
{
	assert(psl);

	CheckCapacity(psl);
	//与头插法思想一致
	for (int i = psl->size -1; i >= pos; i--)
	{
		psl->array[i + 1] = psl->array[i];
	}
	psl->array[pos] = x;
	psl->size++;
}

//删除指定位置的元素
void SeqListErase(SeqList* psl, size_t pos)
{
	assert(psl);

	psl->size--;
	for(int i =pos; i< psl->size;i++)
	{
		psl->array[i] = psl->array[i + 1];
	}
}

//删除给定值的元素
void SeqListRemove(SeqList* psl, SLDataType x)
{
	assert(psl);

	int pos = SeqListFind(psl, x);//利用find函数找到该元素的位置
	if (pos >= 0)
	{
		SeqListErase(psl, pos);//利用删除函数删掉该位置的值即可
	}
}

//修改一个指定位置元素的值
void SeqListModify(SeqList* psl, size_t pos, SLDataType x)
{
	assert(psl || (pos < psl->size));

	psl->array[pos - 1] = x;
}

//打印函数
void SeqListPrint(SeqList* psl)
{
	assert(psl);

	for (int i = 0; i < psl->size; i++)
	{
		cout << psl->array[i] << " ";
	}
	cout << endl; 
}

//冒泡排序
void SeqListBubbleSort(SeqList* psl)
{	
	assert(psl);
	SLDataType tmp;

	for (int i = 0; i < psl->size - 1; i++)
	{
		for (int j = 0; j < psl->size - 1 - i; j++)
		{
			if (psl->array[j] > psl->array[j + 1])
			{
				tmp = psl->array[j];
				psl->array[j] = psl->array[j + 1];
				psl->array[j + 1] = tmp;
			}
		}
	}
}

//二分法查找
int SeqListBinaryFind(SeqList* psl, SLDataType x)
{
	assert(psl);

	int left = 0;
	int right = psl->size - 1;
	int mid;

	while (left <= right)//不要在代码块内部定义变量
	{
		mid = (left + right) / 2;
		if (psl->array[mid] < x)
		{
			left = mid + 1;
		}
		else if (psl->array[mid]>x)
		{
			right = mid - 1;
		}
		else
		{
			return mid;
		}
	}
}

测试

#include"SeqList.h"

int main()
{
	SeqList test;

	SeqListInit(&test, 10);//必须传地址

	SeqListPushBack(&test, 1);
	SeqListPushBack(&test, 2);
	SeqListPushBack(&test, 3);
	SeqListPushBack(&test, 4);
	SeqListPushBack(&test, 5);
	SeqListPushBack(&test, 6);
	SeqListPushBack(&test, 7);
	SeqListPushBack(&test, 8);
	SeqListPushBack(&test, 9);

	SeqListPrint(&test);

	SeqListPopFront(&test);
	SeqListPrint(&test);

	SeqListPopBack(&test);
	SeqListPrint(&test);

	SeqListInsert(&test, 1, 10);
	SeqListPrint(&test);

	SeqListErase(&test, 6);
	SeqListPrint(&test);

	SeqListRemove(&test, 8);
	SeqListPrint(&test);

	SeqListModify(&test, 2, 12);
	SeqListPrint(&test);

	SeqListBubbleSort(&test);
	SeqListPrint(&test);

	cout << SeqListBinaryFind(&test, 6) << endl;

	SeqListDestory(&test);
	system("pause");
	return 0;
}

运行结果
在这里插入图片描述
总结
顺序表插入和删除元素的时间复杂度为O(n),其余操作的时间复杂度均与n无关,故时间复杂度为O(1)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值