数据结构---顺序表

1.线性表
线性表是n个具有相同特性的数据元素的有限序列。常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
在这里插入图片描述
2.顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储。
  2. 动态顺序表:使用动态开辟的数组存储
//动态顺序表
typedef struct seqList
{
	SLDataType* _data;//数组指针
	int _size;//有效元素的个数
	int _capacity;//数组的空间
}seqList;

数据在另外一个空间存放,通过指针找到。
sizeof(seqList):12byte

空间已满:扩容
1.申请更大的空间
2.拷贝原有数据
3.释放原有的空间
4.更新容量
在这里插入图片描述
建立在堆上的,要自己free -----malloc
栈上的不需要
seqListDestory():销毁的是数据的空间
free():销毁的是动态开辟的变量的空间

顺序表的特点

1.空间连续
2.支持随机访问
3.尾插,尾删:O(1)
4.空间利用率高,不容易造成内存碎片
5.其它位置(除了尾部)插入删除:O(n)
6.增容的代价比较大
适合:访问,存储

顺序表接口的实现

#define N 100

typedef int SLDataType;

//顺序表:数组,数组相关信息:有效元素个数,数组的容量
//静态顺序表
struct seqList2
{
	SLDataType _data[N];
	int _size;
};

//动态顺序表
typedef struct seqList
{
	SLDataType* _data;//数组指针
	int _size;//有效元素的个数
	int _capacity;//数组的空间
}seqList;

void initseqList(seqList* s1);//要修改变量内容,传值是拷贝

//操作 :增删查改
//尾插:给顺序表最后一个有效数据的末尾插入新的数据
void seqListPushBack(seqList* s1, SLDataType val);

void seqListcheckCapacity(seqList* s1);

SLDataType seqListAt(seqList* s1, int pos);

void seqListpopBack(seqList* s1);//尾删

void seqListPrint(seqList* s1);

int seqListEmpty(seqList* s1);

int seqListSize(seqList* s1);

void seqListPushFront(seqList* s1, SLDataType val);//头插

void seqListPopFront(seqList* s1);//头删

void seqListInsert(seqList* s1, int pos, SLDataType val);//任意位置插入

void seqListErase(seqList* s1, int pos);//任意位置删除

int seqListFind(seqList* s1, SLDataType val);

void seqListDestroy(seqList* s1);

代码实现:

#include "seqList.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


//初始化一个空的顺序表
void initseqList(seqList* s1)
{
	if (s1 == NULL)
		return;
	s1->_data = NULL;
	s1->_size = 0;
	s1->_capacity = 0;

}
void seqListcheckCapacity(seqList* s1)
{
	if (s1->_size == s1->_capacity)
	{
		//空间已满,扩容
		//1.开新的空间
		int newCapacity = s1->_capacity == 0 ? 1 : 2 * s1->_capacity;
		SLDataType* tmp = (SLDataType*)malloc(newCapacity*sizeof(SLDataType));
		//2.拷贝原有数据
		memcpy(tmp, s1->_data, sizeof(SLDataType)*s1->_size);//按字节拷贝
		//3.释放原有空间
		free(s1->_data);
		s1->_data = tmp;

	//	s1->_data = (SLDataType*)realloc(s1->_data, newCapacity*sizeof(SLDataType));
		
		//4.更新容量
		s1->_capacity = newCapacity;
	}
}
void seqListPushBack(seqList* s1, SLDataType val)//尾插 :时间复杂度:O(1)
{
	seqListcheckCapacity(s1);//检查容量
	//尾插
	s1->_data[s1->_size] = val;
	s1->_size++;
}
void seqListpopBack(seqList* s1)
{
	if (s1 == NULL)
		return;
	if (s1->_size > 0)//有数据才可以删除
		s1->_size--;//假删除
}

void seqListPrint(seqList* s1)
{
	if (s1 == NULL)
		return;
	for (int i = 0; i < s1->_size; ++i)
	{
		printf("%d ", s1->_data[i]);
	}
	printf("\n");
}

SLDataType seqListAt(seqList* s1, int pos)
{
	return s1->_data[pos];
}


int seqListEmpty(seqList* s1)//判断是否为空
{
	if (s1 == NULL || s1->_size == 0)
		return 0;
	else
		return 1;
}


int seqListSize(seqList* s1)
{
	if (s1 == NULL || s1->_size == 0)//s1==NULL判断必须在前,不然做解引用可能会出现问题
		return 0;//程序直接挂掉
	else
		return s1->_size;
}



//头插:移动元素
//移动元素的方向:从后向前移动(防止数据被覆盖)


void seqListPushFront(seqList* s1, SLDataType val)
{
	if (s1 = NULL)
		return;
	seqListcheckCapacity(s1);
	int end = s1->_size;
	while (end > 0)
	{
		s1->_data[end] = s1->_data[end - 1];//第零个元素放到第一个元素的位置
	}
	//插入
	s1->_data[0] = val;
	s1->_size++;
}

void seqListPopFront(seqList* s1)//头删
{
	if (s1 == NULL || s1->_size == 0)
		return;
	//从前向后移动元素
	int start = 1;
	while (start < s1->_size)
	{
		s1->_data[start - 1] = s1->_data[start];//把第一个元素放到第零个元素的位置
		start++;
	}
	//更新size
	s1->_size--;
}

void seqListInsert(seqList* s1, int pos, SLDataType val)
{
	//从pos位置开始移动元素:从后向前
	//从pos位置插入新的元素
	if (s1 = NULL)
		return;
	
	if (pos >= 0 && pos <= s1->_size)
	{
		seqListcheckCapacity(s1);
		//移动元素:[pos,size)
		int end = s1->_size;
		while (end>pos)//pos位置要空出来,不能赋值
		{
			s1->_data[end] = s1->_data[end - 1];
			--end;

		}
		s1->_data[pos] = val;
		s1->_size++;
	}
}


void seqListErase(seqList* s1, int pos)
{
	//任意位置删除:pos   0<=pos<size
	//移动元素:(pos,size) 从前向后移动
	if (s1 == NULL || s1->_size == 0)
		return;
	if (0 <= pos&&pos < s1->_size)
	{
		int start = pos + 1;
		while (start < s1->_size)
		{
			s1->_data[start - 1] = s1->_data[start];
			++start;
		}
		--s1->_size;
	}
}


int seqListFind(seqList* s1, SLDataType val)
{
	if (s1 = NULL)
		return 0;
	for (int i = 0; i < s1->_size; ++i)
	{
		if (s1->_data[i] == val)
			return i;
	}
	return 0;
}



void seqListDestroy(seqList* s1)
{
	if (s1 != NULL&&s1->_data != NULL)
	{
		free(s1->_data);
		s1->_data = NULL;
	}
	//销毁的是数据的空间
}

//free:销毁的是动态开辟的变量的空间



void test()
{
	seqList s1;
	initseqList(&s1);
	
}
int main()
{
	test();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值