数据结构——顺序表(动态)

1.顺序表概念及特点

顺序表是一种线性数据结构,其特点如下:

  1. 存储连续:顺序表使用一块连续的内存空间来存储元素,可以通过下标进行随机访问。这种存储方式使得顺序表的访问效率较高。

  2. 元素有序:顺序表中的元素按照一定的顺序(通常是插入的顺序)排列,每个元素可以通过唯一的下标值进行访问。

  3. 大小固定:顺序表的大小在创建时就确定,无法动态地改变大小,因此需要提前分配好足够的内存空间。

  4. 插入和删除效率较低:由于顺序表的大小固定,插入和删除元素时需要进行元素的后移或前移操作,这样的操作效率较低。尤其是在插入和删除元素的中间位置时,需要移动大量元素。

  5. 随机访问高效:由于元素在顺序表中是连续存储的,并且可以通过下标直接计算出元素的地址,所以随机访问的效率非常高。

  6. 内存开销大:顺序表需要提前分配足够的内存空间来存储元素,如果未能合理估计元素的数量,可能导致内存的浪费。

综上所述,顺序表适用于元素数量固定、频繁进行随机访问的场景,但插入和删除操作相对较慢,且需要提前预估好元素的数量以避免内存浪费。

另外顺序表分为动态和静态
静态就是给定一个容量

#define N 100
typedef int Datetype;

typedef struct Sequence
{
	Datetype array[N];    //定长数组
	size_t number;         //有效数据的个数
};

下面我们详细讲一下动态顺序表

2.图解

在这里插入图片描述

typedef struct Sequence
{
	Date_type* a;
	int number;     //有效数据的个数
	int capacity;  //顺序表的容量
}KT;

我们要通过a和number对表里数据进行一些接口操作,比如增删查改;根据capacity与number的关系决定是否扩容。

下面是完整的程序:
1.头文件程序

#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>

typedef int Date_type;  //增强程序的可维护性,想要改变数据类型,直接在这里面改就可以
//动态顺序表
typedef struct Sequence
{
	Date_type* a;
	int number;     //有效数据的个数
	int capacity;  //顺序表的容量
}KT;


//相关接口函数

void Sequence_init(KT* ps); //初始化接口
void Sequence_print(KT* ps);//打印
void Sequence_destory(KT* ps);//销毁

void Sequence_pushback(KT* ps, Date_type x);  //尾插

void Sequence_pushfront(KT* ps, Date_type x);  //头插
void Sequence_popback(KT* ps);     //尾删
void Sequence_popfront(KT* ps);    //头删
void Sequence_insert(KT * ps, int pos, Date_type x);   //任意位置插入
void Sequence_erase(KT* ps, int pos);         //任意位删除

int Sequen_find(KT* ps, Date_type x);      //查找
void Sequence_modity(KT* ps, int pos, Date_type x);  //

2.函数源文件

#include "sequence.h"

void Sequence_init(KT* ps) //初始化接口
{
	ps->a = NULL;
	ps->number = 0;
	ps->capacity = 0;
}
void Sequence_print(KT* ps)
{
	for (int i = 0; i < ps->number; ++i)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
void Sequence_destory(KT* ps)//销毁
{
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->number = 0;
}

void Sequence_add_newcapacity(KT*ps)
{
	       //检查容量是否慢了,满了则增加容量
	if (ps->number == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		Date_type* tmp = (Date_type*)realloc(ps->a, newcapacity * sizeof(Date_type));
		if (tmp == NULL)
		{
			printf("realloc failed\n");
			exit(-1);    //是一个用于终止程序执行的函数。它的参数 -1 是一个返回值,表示程序执行失败或出现错误的情况。
		}
		else
		{
			ps->a = tmp;
			ps->capacity = newcapacity;
		}
	}
}

void Sequence_pushback(KT* ps, Date_type x) //尾插
{
	//Sequence_add_newcapacity(ps);      //这是第一种方式
	//ps->a[ps->number] = x;
	//ps->number++;


	Sequence_insert(ps, ps->number, x); //这是第二种方式,一个意思

}

void Sequence_pushfront(KT* ps, Date_type x)  //头插
{
	Sequence_add_newcapacity(ps);      //这是第一种方式,查看是否需要增容
	int end = ps->number - 1;
	while (end >= 0)                 //把表里的数据全部向后移动一位,此时a[0]==a[1],可以放心赋值给a[0];
	{
		ps->a[end + 1] = ps->a[end];
		--end;
	}
	ps->a[0] = x;
	ps->number++;

	//Sequence_insert(ps,0,x); //这是第二种方式,一个意思
}
void Sequence_popback(KT* ps)    //尾删
{
	assert(ps->number > 0);

	ps->a[ps->number - 1] = 0;
	ps->number--;

	//Sequence_erase(ps, ps->number - 1);  第二种方式
}
void Sequence_popfront(KT* ps)    //头删
{
	assert(ps->number > 0);

	int first = 1;
	while (first < ps->number)
	{
		ps->a[first - 1] = ps->a[first];   //全部前移一位
		++first;
	}
	ps->number--;

	//Sequence_erase(ps, 0);     //第二种方式

}
void Sequence_insert(KT * ps, int pos, Date_type x)  //任意位置插入
{
	assert(pos <= ps->number);     //断言    插入位置得在数据中
	Sequence_add_newcapacity(ps); 

	int end = ps->number - 1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];   //从要插入的位置开始全部后移一位;
		--end;
	}

	ps->a[pos] = x;
	ps->number++;
}
void Sequence_erase(KT* ps, int pos)         //任意位删除
{
	assert(pos < ps->number);

	int first = pos + 1;
	while (first < ps->number)   //前移一位
	{
		ps->a[first - 1] = ps->a[first];
		++first;
	}
	ps->number--;

}
int Sequen_find(KT* ps, Date_type x)      //查找
{
	for (int i = 0; i < ps->number; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}
void Sequence_modity(KT* ps, int pos, Date_type x)  //修改某个位置的值
{
	assert(pos < ps->number);
	ps->a[pos] = x;
}

3.测试文件(可以接着自行测试)

#include "sequence.h"


void Test_sequence()
{
	KT index;
	Sequence_init(&index);       //传地址是为了直接对顺序表进行修改,如果直接传index,那么将会操作index的副本
	                             //将不会对index产生任何影响
	Sequence_pushback(&index, 0);
	Sequence_pushback(&index, 1);
	Sequence_pushback(&index, 2);
	Sequence_pushback(&index, 3);
	Sequence_pushback(&index, 4);
	Sequence_pushback(&index, 5);
	Sequence_pushback(&index, 6);
	Sequence_print(&index);//打印
	Sequence_destory(&index);//销毁


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

大家有疑问的话欢迎交流。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值