数据结构入门(一)顺序表的实现

在学习数据结构之前,先要了解几个问题

1、什么是数据结构?

答:我们刚开始学习的时候见识的数组就是一个数据结构。数据结构是由“数据”和“结构”两词组织而来的。

数据:生活中的数据随处可见。比如简历上的个人信息,网页里的很多信息,或者是1、2、3这样的数字,手机里保存的图片视频等等,都是数据。

结构:当我们想要大量使用同一类型数据时,通过手动定义大量的独立变量对于程序来说,可读性非常差,我们可以借助数组这样的数据结构将大量的数据组织在一起,结构也可以理解为组织数据的方式。

例如如果想在这样一群没有组织的羊群中找到某一只的话非常困难

但是如果是在羊圈里,那么只需要需要知道这只羊在第几号,然后就可以找到它了。

数据结构:数据结构是计算机存储,组织数据的方式。数据结构是指互相之间存在一种或多种特定关系的数据元素的合集。数据结构反应数据的内部构成,即数据由哪些部分构成,以什么方式构成,以及数据元素之间呈现的结构。

总的来说,数据结构就是

  1. 能够存储数据。
  2. 存储的数据方便查找

2、我们为什么要学习数据结构?

答:如果程序中的数据不能进行有效的管理,可能会导致数据丢失,操作数据困难、野指针等情况。而通过数据结构,我们就可以很好的将数据进行管理。按照我们的方式任意对数据进行增删改查等操作。

3、学习数据结构我们需要掌握哪些知识?

答:我们至少需要掌握结构体、指针、动态内存管理的知识,才能够学习数据结构。

下面进入顺序表的学习。

一、顺序表

1、顺序表的作用

我们之所以实现顺序表,目的就是想要按照我们定义的方式,任意地去对数据进行增删查改的操作,目的在于可以更好地管理所存储的数据,比如我们手机上都有的通讯录,他就可以用顺序表来进行实现。

2、顺序表和数组的区别

顺序表的底层结构是数组,对数组的封装,实现了常用的增删查改等接口。

3、顺序表的分类

顺序表分为:静态顺序表和动态顺序表

静态顺序表:

静态顺序表就是使用的是给定长度的数组来存储数据。下面代码实现的就是静态顺序表。

#define N 7 
typedef int SLDataList;
typedef struct SeqList
{
	SLDataList arr[N];
	int size;
}SL;

静态顺序表是基于数组arr来实现的,并且长度为固定的7个整型。size表示arr数组里所存储的有效数据个数。将int定义为SLDataList是因为,在实际使用顺序表的时候,我们进行管理的内容可能不是int类型,有可能是char或者别的类型。这时候直接把typedef后面的int修改就好了。

缺陷:空间给少了不够用,给多了会造成空间浪费。

如果我们给定的空间不足以存放我们的数据,这可能导致数据丢失,这在工作中是非常严重的技术,所以我们一般不推荐使用静态顺序表,而是使用动态顺序表。

动态顺序表:

特点:按需申请

typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* arr;//储存数据的底层结构
	int capacity;//记录顺序表的空间大小
	int size;//记录顺序表当前有效的数据个数
}SL;

上面就是动态顺序表,与静态顺序表一样,都是在结构体内包含所需要的变量。
代码讲解:
这里与静态顺序表相比用来存储数据的底层结构是一个整形指针arr,并且还多出来一个变量capacity,因为静态顺序表的空间大小是固定的,而动态顺序表的空间大小是可以增容扩大的,所以在动态顺序表里面也必然需要一个变量来表示空间的总大小。

4、动态顺序表的实现

1)、分装文件

对于动态顺序表的实现我们采用分装文件的方法给大家进行讲解。
在VS中创建一个新项目,打开视图,新建一个头文件SeqList.h里面完成定义顺序表的结构,顺序表要实现的接口/方法,再建两个源文件SeqList.cpp和test.cpp分别是实现文件和测试文件,在实现文件中是具体实现顺序表的方法,在测试文件中进行测试顺序表,检查是否存在BUG。

2)、定义动态顺序表

SeqList.h:

#include<stdio.h>
#include<stdlib.h>

//动态顺序表
typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* arr;//储存数据的底层结构
	int capacity;//记录顺序表的空间大小
	int size;//记录顺序表当前有效的数据个数
}SL;

3)、初始化函数SLInit

SeqList.h:

void SLInit(SL* ps);

SeqList.cpp:

void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

4)、数据管理函数头插和尾差以及扩容函数

SeqList.cpp:

扩容函数:

void SLCheckCapcity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		ps->capacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* ptr = (SLDataType*)realloc(ps->arr, sizeof(SLDataType) * ps->capacity);
		if (ptr == NULL)
		{
			perror("realloc fail!");
			exit;
		}
		ps->arr = ptr;
	}
}

尾插函数:

void SLPushBack(SL*ps,SLDataType x)
{
	assert(ps);

	SLCheckCapcity(ps);

	ps->arr[ps->size] = x;
	ps->size++;
}

头插函数

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapcity(ps);

	for (int i = ps->size; i >0; i++)
	{
		ps->arr[i ] = ps->arr[i-1];
	}
	ps->arr[0] = x;
	ps->size++;
}

 SeqList.h:

void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);

5)、头删和为尾删

SeqList.cpp:

头删:

void SLPopFront(SL*ps)
{
	assert(ps);
	assert(ps->size);

	for (int i = 0; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

6)、指定位置插入、删除

SeqList.cpp:

指定位置插入:

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos > 0 && pos <= ps->size);
	if (pos==ps->size+1)
	{
		SLCheckCapcity(ps);
		SLPushBack(ps, x);
	}
	else
	{
		SLCheckCapcity(ps);
		for (int i = ps->size; i > =pos; i--)
		{
			ps->arr[ps->size] = ps->arr[ps->size - 1];
		}
		ps->arr[pos - 1] = x;
		ps->size++;
	}
}

指定位置删除

void SLEraes(SL* ps,int pos)
{
	assert(ps);
	assert(pos > 0 && pos < ps->size + 1);
	for(int i=pos;i<ps->size;i++)
	{
		ps->arr[i - 1] = ps->arr[i];
	}
	ps->size--;
}

7)、查找函数

SeqList.cpp:

int SLFind(SL* ps, SLDataType x)
{
	assert(ps);

	for (int i = 0; i < ps->size; i++)
	{
		if (x == ps->arr[i])
		{
			return i + 1;
		}
	}
	return -1;
}

8)、销毁函数

SeqList.cpp:

void SLDestroy(SL* ps)
{
	assert(ps);

	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

二、完整代码

SeqList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//动态顺序表
typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* arr;//储存数据的底层结构
	int capacity;//记录顺序表的空间大小
	int size;//记录顺序表当前有效的数据个数
}SL;

void SLInit(SL* ps);

void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);


void SLDestroy(SL* ps);
int SLFind(SL* ps, SLDataType x);
void SLEraes(SL* ps, int pos);

void SLInsert(SL* ps, int pos, SLDataType x);
void SLPopFront(SL* ps);
void SLPopBack(SL* ps);

SeqList.cpp

//动态顺序表
#include"SeqList.h"

void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

void SLCheckCapcity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		ps->capacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* ptr = (SLDataType*)realloc(ps->arr, sizeof(SLDataType) * ps->capacity);
		if (ptr == NULL)
		{
			perror("realloc fail!");
			exit;
		}
		ps->arr = ptr;
	}
}

void SLPushBack(SL*ps,SLDataType x)
{
	assert(ps);

	SLCheckCapcity(ps);

	ps->arr[ps->size] = x;
	ps->size++;
}

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapcity(ps);

	for (int i = ps->size; i >0; i++)
	{
		ps->arr[i ] = ps->arr[i-1];
	}
	ps->arr[0] = x;
	ps->size++;
}

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);

	ps->size--;
}

void SLPopFront(SL*ps)
{
	assert(ps);
	assert(ps->size);

	for (int i = 0; i < ps->size-1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos > 0 && pos <= ps->size);
	if (pos==ps->size+1)
	{
		SLCheckCapcity(ps);
		SLPushBack(ps, x);
	}
	else
	{
		SLCheckCapcity(ps);
		for (int i = ps->size; i > =pos; i--)
		{
			ps->arr[ps->size] = ps->arr[ps->size - 1];
		}
		ps->arr[pos - 1] = x;
		ps->size++;
	}
}

void SLEraes(SL* ps,int pos)
{
	assert(ps);
	assert(pos > 0 && pos < ps->size + 1);
	for(int i=pos;i<ps->size;i++)
	{
		ps->arr[i - 1] = ps->arr[i];
	}
	ps->size--;
}


int SLFind(SL* ps, SLDataType x)
{
	assert(ps);

	for (int i = 0; i < ps->size; i++)
	{
		if (x == ps->arr[i])
		{
			return i + 1;
		}
	}
	return -1;
}

void SLDestroy(SL* ps)
{
	assert(ps);

	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->size = 0;
}

  • 23
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

名亡实存

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值