【数据结构初阶】顺序表和链表

1.线性表

        线性表指的是具有部分相同特性的⼀类数据结构的集合,它是由零个或多个数据元素组成的有限序列。
        线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。

        常见的线性表:顺序表、链表、栈、队列、字符串......

        顺序表是使用一组连续的存储单元依次存储线性表的数据元素。链表则是通过节点将数据元素链接起来,节点包含数据域和指针域,指针域用于指向下一个节点。

2.顺序表

顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。它使用一组地址连续的存储单元依次存储线性表中的元素。顺序表分为静态顺序表和动态顺序表。

1.静态顺序表

静态顺序表
typedef int Seqdatatype;
#define N 10
typedef struct SeqList
{
	Seqdatatype a[N];  //定长数组
	int size;          //有效数据个数

}sl;

静态顺序表是指采用静态数组来实现的顺序表。它在使用前需要预先分配固定大小的存储空间,一旦分配完成,其容量就不能再改变。
静态顺序表的优点是实现简单,操作直观。
缺点也较为明显:空间大小固定,可能会出现存储空间不足或者浪费的情况。

2.动态顺序表

动态顺序表是在顺序表的基础上,能够根据实际需求动态地调整存储空间大小。它的实现通常基于底层的数组,当现有存储空间不足时,会重新分配一块更大的连续存储空间,并将原数据复制到新的空间中。
 动态顺序表的优点在于:
1. 能够更灵活地适应数据规模的变化,避免了因存储空间固定而导致的数据存储受限问题。
2. 相对于链表,它在随机访问上具有更高的效率。
 不足之处在于:
1. 动态扩展存储空间时,涉及数据的复制操作,会带来一定的时间开销。
2. 频繁的扩展操作可能导致内存碎片的产生。
 在实际应用中,如果需要高效的随机访问,同时数据规模不确定或可能发生较大变化,动态顺序表是一个较好的选择。

typedef struct SeqList
{
	Seqdatatype* arr;
	int size;       //有效数据个数
	int capacity;   //空间大小
}SL;

下面是动态顺序表的实现:

我们将在三个文件中实现动态顺序表,头文件SeqList.h中实现函数的声明,源文件SeqList中实现函数的定义

 text.c :

#include "SeqList.h"

test1()
{
	SL sl;
	SLInit(&sl);

	//尾插
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPrint(sl);
	//头插
	SLPushFront(&sl, 9);
	SLPushFront(&sl, 8);
	SLPushFront(&sl, 7);
	SLPrint(sl);
	//尾删
	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPrint(sl);
	//头删
	SLPopFront(&sl);
	SLPopFront(&sl);
	SLPrint(sl);
	//指定位置
	SLInsert(&sl, 66, 2);
	SLPrint(sl);
	//指定删除
	SLErase(&sl, 1);
	SLPrint(sl);
	//查找数据
	int find = SLFind(&sl, 66);
	if (find < 0)
	{
		printf("没找到\n");
	}
	else
	{
	    printf("找到了\n", find);
	}

	SLDestory(&sl);

}

int main()
{
	test1();
	return 0;
}

SeqList.h:

#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include 
#include 
#include 

typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* data;
	int size;
	int Capacity;
}SL;

//初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestory(SL* ps);
//打印
void SLPrint(SL s);
//判断空间充足
void SLCheckCapacity(SL* ps);
//尾插
void SLPushBack(SL* ps , SLDataType x);
//头插
void SLPushFront(SL* ps, SLDataType x);
//尾删
void SLPopBack(SL* ps);
//头删
void SLPopFront(SL* ps);
//指定位置之前插入数据
void SLInsert(SL* ps, SLDataType x,int pos);
//指定位置删除数据
void SLErase(SL* ps, int pos);
//查找数据
int SLFind(SL* ps, SLDataType x);

SeqList.c:  

#include "SeqList.h"

//初始化
void SLInit(SL* ps)
{
	ps->data = NULL;
	ps->size = ps->Capacity = 0;
}

//顺序表的销毁
void SLDestory(SL* ps)
{
	if(ps)
	{
		free(ps->data);
	}
	ps->data = NULL;
	ps->size = ps->Capacity = 0;
}

//打印
void SLPrint(SL s)
{
	for(int i = 0;i size == ps->Capacity)
	{
		int NewCapacity = ps->Capacity == 0 ? 4 : 2 * ps->Capacity;
		SLDataType* tmp = (S

你可能感兴趣的:(链表,数据结构)