数据结构----顺序表

本文详细介绍了顺序表的数据结构,包括静态顺序表和动态顺序表的概念,以及它们的初始化、销毁、空间管理、尾插、头插、查找、插入和删除等基础功能的实现。
摘要由CSDN通过智能技术生成

认识了解顺序表

a.顺序表的概念

在数据结构中,顺序表是一种线性表的存储结构,它是由一组地址连续的存储单元依次存储线性表的各个元素。顺序表有两种形式:静态顺序表和动态顺序表。

静态顺序表(Static Array): 在创建时就确定了固定大小,不可改变。静态顺序表的元素在物理地址上是连续存储的,支持随机访问,通过下标可以直接访问任意位置的元素。

//顺序表的静态存储
define N 7
//SLDataType 是一个整数类型的别名,
//DataType仅仅只是作为表示符,无实际作用
typedef int SLDataType 
typedef struct seqlist
{
   //定义顺序表的长度
	SLDataType array[n];
   //有效数据个数,顺序表中实际存储的元素数量
	size_t  size;
}seqlist;

在这里插入图片描述

动态顺序表(Dynamic Array): 具有动态分配和扩展的特性。最典型的例子是动态数组(Dynamic Array),比如在一些编程语言中的 ArrayList(Java)或 Vector(C++),它们可以根据需要动态调整内存空间,允许在数组末尾高效地进行元素的插入和删除操作。

/顺序表的动态存储
//SLDataType 是一个整数类型的别名,
//DataType仅仅只是作为表示符,无实际作用
typedef int SLDataType 
typedef struct seqlist
{
	    // 指向动态开辟的数组,存储数据元素
		SLDataType* array; 
		//有效数据个数,顺序表中实际存储的元素数量
		size_t size; 
		// 容量空间的大小
		size_t capicity; 
}seqlist;

在这里插入图片描述

顺序表的优点是支持随机访问,元素存储在一块连续的内存空间中,这使得通过索引直接访问元素非常快速。然而,它的缺点是在插入和删除操作时可能需要移动大量元素,导致操作效率降低。

顺序表的基础功能实现(接口实现)

函数声明

#pragma once
// 顺序表的动态存储
//SLDataType 是一个整数类型的别名,
//DataType仅仅只是作为表示符,无实际作用
typedef int SLDataType;
typedef struct SeqList
{
	// 指向动态开辟的数组,存储数据元素
	SLDataType* a;
	//有效数据个数,顺序表中实际存储的元素数量
	int size;
	// 容量空间的大小
	int capicity;
}SL;
void SLInit(SL* ps1);//顺序表的初始化
void SLDestory(SL* ps1);//顺序表的销毁
void CheckCapacity(SL* psl);// 检查空间,如果满了,进行增容
void SLPushBack(SL* psl, SLDataType x); //顺序表的尾插
void SLPrint(SL* ps1);//顺序表的打印
void SLPopBack(SL* ps1);//顺序表的尾删
void SLPushFront(SL* ps1, SLDataType x); //顺序表的头插
void SLPopFront(SL* ps1);//顺序表的头删;
int SLFind(SL* ps1, SLDataType x); //顺序表的查找
void SLInsert(SL* ps1, int pos, SLDataType x); //顺序表在任意位置插入
void SLErase(SL* ps1, int pos); //顺序表在任意位置删除数据

a.顺序表的初始化

//顺序表的初始化
void SLInit(SL* psl)
{
	psl->a = NULL;
	psl->size = 4;  //初态的顺序表的成员为4
	psl->capicity = 0; //
}

动态顺序表的结构中包含一个指针,防止指针成为野指针,将指针指向空.

b.顺序表的销毁

void SLDestory(SL* ps1) //顺序表的销毁
{
	while (ps1->a != NULL)
	{
		free(ps1->a);
		ps1->a = NULL;
		ps1->size = 0;
		ps1->capicity = 0;
	}
}

c.顺序表的空间扩容

void CheckCapacity(SL* ps1)  //检查扩容
{
	if (ps1->size == ps1->capacity)
	{
		int newCapacity = ps1->capacity == 0 ? 4 : ps1->capacity * 2; //三目操作符
		SLDataType* tmp = (SLDataType*)realloc(ps1->a, sizeof(SLDataType) * newCapacity);  //void* realloc (void* ptr, size_t size);
		if (tmp == NULL)  //判断是否扩容成功
		{
			perror("realloc fail");   //打印错误原因
			return;
		}
		ps1->a = tmp;
		ps1->capacity = newCapacity;
	}
}

d.顺序表的尾插

尾插:在顺序表的末尾插入一个元素.
在这里插入图片描述

void SLPushBack(SL* ps1, SLDataType x)  //顺序表的尾插
{
	CheckCapacity(ps1);  //检查扩容
	ps1->a[ps1->size] = x;
	ps1->size++;
}

e.顺序表的尾删

尾删:删除顺序表末尾的元素.

在这里断言是为了防止访问到size为负数的情况,造成越界访问的问题.
在这里插入图片描述

void SLPopBack(SL* ps1) //顺序表的尾删
{
	assert(ps1->size);
	ps1->size--;

}

f.顺序表的头插

在这里插入图片描述

void SLPushFront(SL* ps1, SLDataType x)  //顺序表的头插
{
	CheckCapacity(ps1);
	int end = ps1->size-1;
	while (end>=0)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[0] = x;
	ps1->size++;
}

g.顺序表的头删

在这里插入图片描述

这里断言是为了,防止进行n次头删操作后,顺序表中没有元素了,再次进行头删操作,造成越界访问的问题.

void SLPopFront(SL* ps1) //顺序表的头删
{
	assert(ps1->size);
	int begin = 1;
	while (begin<ps1->size)
	{
		ps1->a[begin - 1] = ps1->a[begin];
		begin++;
	}
	ps1->size--;
}

h.顺序表的查找

int SLFind(SL* ps1, SLDataType x) //顺序表的查找
{
	for (int i = 0; i < ps1->size; i++)
	{
		if (ps1->a[i] == x)
		{
			//return i;
			printf("%d\n", ps1->a[i]);
		}
		}
	return -1;
}

i,顺序表任意位置插入

在这里插入图片描述
把特殊的情况都去除掉,一般这些情况我们都是需要通过if 来判断的,现在就相当于一个暴力的检测

oid SLInsert(SL* ps1, int pos, SLDataType x) //顺序表在任意位置插入
{
	CheckCapacity(ps1);
	assert(pos>=0&&pos<=ps1-size);
	int end = ps1->size - 1;
	while (end >= pos)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[pos] = x;
	ps1->size++;
}

j.顺序表任意位置删除

在这里插入图片描述
把特殊的情况都去除掉,一般这些情况我们都是需要通过if 来判断的,现在就相当于一个暴力的检测

void SLErase(SL* ps1, int pos) //顺序表在任意位置删除数据
{
assert(pos >= 0 && pos < ps->size);
assert(ps1->size);
	int begin = pos;
	while (pos<ps1->size)
	{
		ps1->a[begin-1] = ps1->a[begin];
		pos++;
		begin++:
	}
	ps1->size--;
}

完整代码

函数声明

#pragma once
// 顺序表的动态存储
//SLDataType 是一个整数类型的别名,
//DataType仅仅只是作为表示符,无实际作用
typedef int SLDataType;
typedef struct SeqList
{
	// 指向动态开辟的数组,存储数据元素
	SLDataType* a;
	//有效数据个数,顺序表中实际存储的元素数量
	int size;
	// 容量空间的大小
	int capacity;
}SL;
void SLInit(SL* ps1);//顺序表的初始化
void SLDestory(SL* ps1);//顺序表的销毁
void CheckCapacity(SL* psl);// 检查空间,如果满了,进行增容
void SLPushBack(SL* psl, SLDataType x); //顺序表的尾插
void SLPrint(SL* ps1);//顺序表的打印
void SLPopBack(SL* ps1);//顺序表的尾删
void SLPushFront(SL* ps1, SLDataType x); //顺序表的头插
void SLPopFront(SL* ps1);//顺序表的头删;
int SLFind(SL* ps1, SLDataType x); //顺序表的查找
void SLInsert(SL* ps1, int pos, SLDataType x); //顺序表在任意位置插入
void SLErase(SL* ps1, int pos); //顺序表在任意位置删除数据


函数的定义

//定义
#include "seqlist.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
void SLInit(SL* ps1)//顺序表的初始化
{
	ps1->a = NULL;
	ps1->size = 0;
	ps1->capacity = 0;
}
void SLDestory(SL* ps1) //顺序表的销毁
{
	if(ps1->a != NULL)
	{
		free(ps1->a);
		ps1->a = NULL;
		ps1->size = 0;
		ps1->capacity = 0;
	}
}
void SLPrint(SL* ps1)//顺序表的打印
{
	for (int i = 0; i < ps1->size; i++)
	{
		printf("%d ", ps1->a[i]);
	}
	printf("\n");
}

void CheckCapacity(SL* ps1)  //检查扩容
{
	if (ps1->size == ps1->capacity)
	{
		int newCapacity = ps1->capacity == 0 ? 4 : ps1->capacity * 2; //三目操作符
		SLDataType* tmp = (SLDataType*)realloc(ps1->a, sizeof(SLDataType) * newCapacity);  //void* realloc (void* ptr, size_t size);
		if (tmp == NULL)  //判断是否扩容成功
		{
			perror("realloc fail");   //打印错误原因
			return;
		}
		ps1->a = tmp;
		ps1->capacity = newCapacity;
	}
}
void SLPushBack(SL* ps1, SLDataType x)  //顺序表的尾插
{
	CheckCapacity(ps1);  //检查扩容
	ps1->a[ps1->size] = x;
	ps1->size++;
}
void SLPopBack(SL* ps1) //顺序表的尾删
{
	assert(ps1->size);
	ps1->size--;

}
void SLPushFront(SL* ps1, SLDataType x)  //顺序表的头插
{
	CheckCapacity(ps1);
	int end = ps1->size-1;
	while (end>=0)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[0] = x;
	ps1->size++;
}
void SLPopFront(SL* ps1) //顺序表的头删
{
	assert(ps1->size);
	int begin = 1;
	while (begin<ps1->size)
	{
		ps1->a[begin - 1] = ps1->a[begin];
		begin++;
	}
	ps1->size--;
}
int SLFind(SL* ps1, SLDataType x) //顺序表的查找
{
	for (int i = 0; i < ps1->size; i++)
	{
		if (ps1->a[i] == x)
		{
			//return i;
			printf("%d\n", ps1->a[i]);
		}
		}
	return -1;
}
void SLInsert(SL* ps1, int pos, SLDataType x) //顺序表在任意位置插入
{
	CheckCapacity(ps1);
	int end = ps1->size - 1;
	while (end >= pos)
	{
		ps1->a[end + 1] = ps1->a[end];
		end--;
	}
	ps1->a[pos] = x;
	ps1->size++;
}
void SLErase(SL* ps1, int pos) //顺序表在任意位置删除数据
{
	assert(ps1->size);
	int begin = pos;
	while (pos<=ps1->size)
	{
		ps1->a[pos-1] = ps1->a[pos];
		begin++;
		pos++;
	}
	ps1->size--;
}

函数测试

#include<stdio.h>
#include "seqlist.h"
void test1()
{
	SL s1;
	SLInit(&s1);
	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPushBack(&s1, 4);
	SLPushBack(&s1, 5);
	SLPushBack(&s1, 6);
	/*SLPopBack(&s1);
	SLPushFront(&s1, 10);
	SLPushFront(&s1, 20);
	SLPopFront(&s1);
	SLPopFront(&s1);
	SLPopFront(&s1);*/
	//SLFind(&s1, 4);
	//SLErase(&s1, 2);
	SLFind(&s1, 4);
	//SLPrint(&s1);
	SLDestory(&s1);
}
void test2()
{
	SL s1;
	SLInit(&s1);
	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPushBack(&s1, 4);
	SLPushBack(&s1, 5);
	SLPushBack(&s1, 6);
	//SLFind(&s1, 4);
	SLErase(&s1, 3);
	//SLErase(&s1, 4);
	SLFind(&s1, 4);
	SLPrint(&s1);
	SLDestory(&s1);
}
int main()
{
	//test1();
	test2();
}
  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值