数据结构之顺序表

前言

介绍顺序表之前先介绍一下线性表,线性表是一种常见的数据结构,它是最基本的线性数据结构之一。线性表中的数据元素之间存在一对一的线性关系,即每个元素(除了第一个和最后一个)都有一个直接前驱和一个直接后继。线性表是一个有限序列,包含0个或多个数据元素,线性表中的所有数据元素具有相同的数据类型。线性表一般有2种存储方式,一种是顺序存储,另一种是链式存储。而顺序表便是线性表顺序存储方式的体现。

基本概念

顺序表是一种线性表的存储方式,其中数据元素按照逻辑顺序依次存储在内存中的一块连续空间内。每个数据元素在内存中的位置可以通过其索引(或下标)快速计算得到。

特点

  • 存储结构:顺序表是基于数组实现的,数据元素在内存中连续存放。

  • 随机访问:可以通过索引快速访问任意位置的元素,时间复杂度为 O(1)

  • 插入和删除操作效率低:插入或删除元素时,通常需要移动大量元素以保持存储空间的连续性,时间复杂度为 O(n),其中 n 是表的长度。

  • 空间利用率:顺序表需要预先分配存储空间,可能会导致空间浪费(分配过大)或存储空间不足(分配过小)。

初始化顺序表

首先定义顺序表结构体,然后定义初始化函数,申请空间并初始化数组和长度,之后返回指向该顺序表的指针。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 10  //顺序表中最大元素个数
typedef struct
{
	int data[MAX_LEN];//存储数据元素
	int len;//当前顺序表长度
}sqlist_t;

static sqlist_t* sqlist_init()
{
	sqlist_t* sq = (sqlist_t*)malloc(sizeof(sqlist_t));//申请空间
	if (sq != NULL)
	{
		memset(sq->data, 0, MAX_LEN);
		sq->len = 0;
		return sq;//初始化数组和长度后返回顺序表指针
	}
}
int main()
{
	sqlist_t* s = sqlist_init();
	return 0;
}

增加元素

增加元素即插入元素,这一步实现插入函数。顺序表不限制插入元素的位置,可以用一个形参来指定插入的位置。

顺序表在进行插入时需要大量移动元素。比如:如果原先顺序表里是1,2,3,4,此时想在2,3之间插入5,那么就需要将3,4各往后移动一个位置,此时就空了一个位置出来,再把5放进去。

/*
插入函数,sq为待插入的顺序表,pos表示插入的位置(最小为1),value为待插入的数据
*/
static int sqlist_insert(sqlist_t* sq, int pos, int value)
{
	if (sq->len > MAX_LEN || pos<1 || pos > sq->len+1)//错误处理
	{
		return -1;
	}
	for (int i = sq->len - 1;i >= pos-1;i--)
	{
		sq->data[i + 1] = sq->data[i];//依次往后移动
	}
	sq->data[pos - 1] = value;// 对插入位置赋值
	sq->len++;//长度记得+1
	return 0;
}

static void sqlist_show(sqlist_t* sq)  //打印函数
{
	for (int i = 0;i < sq->len;i++)
	{
		printf("%d ",sq->data[i]);
	}
	printf("\n");
}
int main()
{
	sqlist_t* s = sqlist_init();
	for (int i = 0;i < 4;i++)
	{
		sqlist_insert(s,i+1,i+1);//利用循环插入 1 2 3 4
	}
	sqlist_show(s);

	sqlist_insert(s, 3, 5);//在第三个位置,即2和3之间插入5
	sqlist_show(s);
	return 0;
}

输出结果: 

删除元素

用一个指针p将要删除位置的元素读走后,其余元素依次移动一位,最后更新顺序表的长度(减一)。

static int sqlist_delete(sqlist_t* sq, int pos,int* p)
{
	if (pos<1 || pos>sq->len || sq->len > MAX_LEN)
	{
		return -1;
	}
	*p = sq->data[pos - 1];
	for(int i=pos;i<sq->len;i++)
	{
		sq->data[i - 1] = sq->data[i];
	}
	sq->len--;
	return 0;
}


int main()
{
	int p;
	sqlist_t* s = sqlist_init();
	for (int i = 0;i < 4;i++)
	{
		sqlist_insert(s,i+1,i+1);
	}
	sqlist_show(s);

	sqlist_insert(s, 3, 5);
	sqlist_show(s);
	sqlist_insert(s, 4, 3);
	sqlist_show(s);
	sqlist_insert(s, 5, 7);
	sqlist_show(s);
	sqlist_delete(s, 6,&p);
	sqlist_show(s);

	return 0;
}

输出结果:

查找元素

对数组的查找操作可以有很多种优化方法,本文暂时只介绍最基本的。

static int sqlist_search(sqlist_t* sq,int value)
{
	for (int i = 0;i < sq->len;i++)
	{
		if (sq->data[i] == value)
		{
			return i + 1;//对数组进行暴力搜索,找到目标值就返回其位置,否则返回-1
		}
	}
	return -1;
}

int main()
{
	int p;
	sqlist_t* s = sqlist_init();
	for (int i = 0;i < 4;i++)
	{
		sqlist_insert(s,i+1,i+1);
	}
	sqlist_show(s);

	sqlist_insert(s, 3, 5);
	sqlist_show(s);
	sqlist_insert(s, 4, 3);
	sqlist_show(s);
	sqlist_insert(s, 5, 7);
	sqlist_show(s);
	sqlist_delete(s, 6,&p);
	sqlist_show(s);

	int res = sqlist_search(s, 7);
	if (res > 0)
	{
		printf("找到了7,位置为:%d\n", res);
	}
	else
		printf("没找到7\n");


	int res2 = sqlist_search(s, 9);
	if (res2 > 0)
	{
		printf("找到了9,位置为:%d\n", res2);
	}
	else
		printf("没找到9\n");
	return 0;
}


输出结果:

 

修改元素

这里的逻辑就是直接对要修改的位置重新赋值。

static int sqlist_alter(sqlist_t* sq, int pos, int new)
{
	if (pos > sq->len || sq->len > MAX_LEN)
	{
		return -1;//错误处理
	}
	sq->data[pos - 1] = new;//直接对要修改的位置重新赋值
	return 0;
}


int main()
{
	int p;
	sqlist_t* s = sqlist_init();
	for (int i = 0;i < 4;i++)
	{
		sqlist_insert(s,i+1,i+1);
	}
	sqlist_show(s);

	sqlist_insert(s, 3, 5);
	sqlist_show(s);
	sqlist_insert(s, 4, 3);
	sqlist_show(s);
	sqlist_insert(s, 5, 7);
	sqlist_show(s);
	sqlist_delete(s, 6,&p);
	sqlist_show(s);

	int res = sqlist_search(s, 7);
	if (res > 0)
	{
		printf("找到了7,位置为:%d\n", res);
	}
	else
		printf("没找到7\n");

	sqlist_alter(s, res, 9);
	sqlist_show(s);

	int res1 = sqlist_search(s, 7);
	if (res1 > 0)
	{
		printf("找到了7,位置为:%d\n", res1);
	}
	else
		printf("没找到7\n");

	int res2 = sqlist_search(s, 9);
	if (res2 > 0)
	{
		printf("找到了9,位置为:%d\n", res2);
	}
	else
		printf("没找到9\n");
	return 0;
}

输出结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值