数据结构顺序表(定长与不定长)用c语言实现

目录

1.线性表的定义

[2. 定长顺序表](#2. 定长顺序表)

[2.1 定长顺序表的结构](#2.1 定长顺序表的结构)

[2.2 结构示意图](#2.2 结构示意图)

[2.3 实现顺序表的操作(重点)](#2.3 实现顺序表的操作(重点))

3.不定长顺序表

[3.1 不定长顺序表结构](#3.1 不定长顺序表结构)

[3.2 结构示意图](#3.2 结构示意图)

[3.3 不定长顺序表的实现(重点)](#3.3 不定长顺序表的实现(重点))

4.顺序表总结


1.线性表的定义

存在唯一的一个被称为"第一个"的数据元素;

存在唯一的一个被称为"最后一个"的数据元素;

除第一个之外,集合中的每一个数据元素都只有一个前驱;

除最后一个之外,集合中的每一个数据元素都只有一个后继;

线性表是最简单最常用的一种线性表。

线性表分为顺序表和链表。

顺序表又分为定长顺序表和不定长顺序表。

2.定长顺序表

2.1 定长顺序表的结构

加入length和左端连续。

cpp 复制代码
//定义与声明
typedef struct SQList {//定长顺序表的结构
	int elem[10];//存放数据,固定长度为10
	int length;//有效数据的长度
}SQList,*PSQList;

2.2 结构示意图

2.3 实现顺序表的操作**(重点)**

cpp 复制代码
//不定长顺序表的实现

#include "sqlist.h"
#include <stdio.h>
#include <assert.h>

//初始化
void InitSqlist(PSQList ps)
{
	assert(ps != NULL);
	if (ps == NULL)
		return;

	ps->length = 0;
}

static bool IsFul(PSQList ps)
{
	return ps->length == 10;
}

//插入数据,在ps顺序表的pos位置插入val;
bool Insert(PSQList ps, int pos, int val)
{
	assert(ps != NULL);
	if (ps == NULL)
		return false;

	if (pos<0 || pos>ps->length || IsFul(ps))
	{
		return false;
	}
	//把数据移动到后面
	for (int i = ps->length - 1; i >= pos; i--)
	{
		ps->elem[i + 1] = ps->elem[i];
	}
	//插入数据
	ps->elem[pos] = val;
	//有效数据个数++;
	ps->length++;	
	return true;
}

//判空
bool IsEmpty(PSQList ps)
{
	return ps->length == 0;
}

//在ps中查找第一个key值,找到返回下标,没有找到返回-1;
int Search(PSQList ps, int key)
{
	for (int i = 0; i < ps->length; i++)
	{
		if (key == ps->elem[i])
			return i;
	}
	return -1;
}

//删除pos位置的值
bool DelPos(PSQList ps, int pos)
{
	assert(ps != NULL);
	if (ps == NULL)
		return false;

	if (pos<0 || pos>=ps->length)
	{
		return false;
	}
	//将后面的数据前移
	for (int i = pos; i < ps->length - 1; i++)
	{
		ps->elem[i] = ps->elem[i + 1];
	}
	//有效数据个数--;
	ps->length--;
	return true;
}

//删除第一个val的值
bool DelVal(PSQList ps, int val)
{
	int  i = Search(ps, val);
	if (i < 0)
		return false;

	return DelPos(ps, i);
}

//返回key的前驱下标,如果不存在返回-1;
int GetPrio(PSQList ps, int key)
{
	int i = Search(ps, key);
	if (i <= 0)//注意头没有前驱
		return -1;

	return i - 1;
}

//返回key的后继下标,如果不存在返回-1;
int GetNext(PSQList ps, int key)
{
	int i = Search(ps, key);
	if (i < 0 || i == ps->length - 1)//注意,尾没有后继
		return -1;

	return i + 1;
}

//输出
void Show(PSQList ps)
{
	assert(ps != NULL);
	if (ps == NULL)
		return;

	for (int i = 0; i < ps->length; i++)
	{
		printf("%d  ", ps->elem[i]);
	}
	printf("\n");
}

//清空数据
void Clear(PSQList ps)
{
	ps->length = 0;
}

//销毁整个内存
void Destroy(PSQList ps)
{
	Clear(ps);
}

3.不定长顺序表

3.1 不定长顺序表结构

cpp 复制代码
typedef struct DSQList {
	int* elem;//动态内存的地址
	int length;//有效数据的个数
	int listsize;//总容量
}DSQList,*DPSQList;

3.2 结构示意图

很明显,为了能实现扩容(否则如何实现再次判满呢?),我们必须要在定长顺序表的基础上增加一个总容量;结构示意图如下:

3.3 不定长顺序表的实现(重点)

cpp 复制代码
//初始化
void InitSqlist(DPSQList ps)
{
	assert(ps != NULL);
	if (ps == NULL)
		return;

	ps->elem = (int*)malloc(INIT_SIZE * sizeof(int));
	ps->length = 0;
	ps->listsize = INIT_SIZE;
}
static bool IsFull(DPSQList ps)
{
	return ps->length == ps->listsize;
}

static bool Inc(DPSQList ps)
{
	ps->elem = (int*)realloc(ps->elem, ps->listsize * 2 * sizeof(int));
	assert(ps->elem != NULL);
	ps->listsize *= 2;
	//ps->length;
	return true;
}

//插入数据,在ps顺序表的pos位置插入val;
bool Insert(DPSQList ps, int pos, int val)
{
	assert(ps != NULL);
	if (ps == NULL)
		return false;

	if (pos<0 || pos>ps->length)
	{
		return false;
	}
	if (IsFull(ps))
	{
		Inc(ps);
	}
	//把数据往后移
	for (int i = ps->length - 1; i >= pos; i--)
	{
		ps->elem[i + 1] = ps->elem[i];
	}
	//插入新数据
	ps->elem[pos] = val;
	//有效数据个数++
	ps->length++;

	return true;
}

//判空
bool IsEmpty(DPSQList ps)
{
	return ps->length == 0;
}

//在ps中查找第一个key值,找到返回下标,没有找到返回-1;
int Search(DPSQList ps, int key)
{
	for (int i = 0; i < ps->length; i++)
	{
		if (key == ps->elem[i])
			return i;
	}
	return -1;
}

//删除pos位置的值
bool DelPos(DPSQList ps, int pos)
{
	assert(ps != NULL);
	if (ps == NULL)
		return false;

	if (pos < 0 || pos >= ps->length)
	{
		return false;
	}
		//后面的数据前移
	for (int i = pos; i < ps->length - 1; i++)
	{
		ps->elem[i] = ps->elem[i + 1];
	}
		//有效数据--;
	ps->length--;
	return true;
}

//删除第一个val的值
bool DelVal(DPSQList ps, int val)
{
	int i = Search(ps, val);
	if (i < 0)
		return false;

	return DelPos(ps, i);
}

//返回key的前驱下标,如果不存在返回-1;
int GetPrio(DPSQList ps, int key)
{
	int i = Search(ps, key);
	if (i <= 0)
		return -1;

	return i - 1;
}

//返回key的后继下标,如果不存在返回-1;
int GetNext(DPSQList ps, int key)
{
	int i = Search(ps, key);
	if (i < 0 || i == ps->length - 1)
		return -1;

	return i + 1;
}

//输出
void Show(DPSQList ps)
{
	assert(ps != NULL);
	if (ps == NULL)
		return;
	for (int i = 0; i < ps->length; i++)
	{
		printf("%d  ", ps->elem[i]);
	}
	printf("\n");
}

//清空数据
void Clear(DPSQList ps)
{
    ps->length=0;
}

//销毁整个内存
void Destroy(DPSQList ps)
{
	free(ps->elem);
	ps->elem = NULL;
	ps->length = 0;
	ps->listsize = 0;
	ps = NULL;//无效的代码
}

4.顺序表总结

顺序表的特点:

1.插入数据的时间复杂度是O(n),如果是尾插时间复杂度是O(1);

2.删除数据的时间复杂度是O(n),如果是尾删时间复杂度是O(1);

3.通过下标访问数据时间复杂度是O(1);

  • 顺序表逻辑上相邻的元素物理上也相邻,所以插入和删除操作需要移动大量元素;
  • 存储密度大(高),每个结点只存储数据元素(对比链表);
  • 随机访问:顺序表是一种支持随机存取的存储结构,根据起始地址加上元素的序号,可以在O(1)时间内找到指定的元素,这就是随机存取的概念;
相关推荐
1nullptr2 小时前
三次翻转实现数组元素的旋转
数据结构
TT哇2 小时前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
嵌入式科普2 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
A懿轩A2 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
1 9 J3 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
汝即来归4 小时前
选择排序和冒泡排序;MySQL架构
数据结构·算法·排序算法
仍然探索未知中4 小时前
C语言经典100例
c语言
爱吃西瓜的小菜鸡5 小时前
【C语言】矩阵乘法
c语言·学习·算法
Stark、6 小时前
【Linux】文件IO--fcntl/lseek/阻塞与非阻塞/文件偏移
linux·运维·服务器·c语言·后端
deja vu水中芭蕾6 小时前
嵌入式C面试
c语言·开发语言