[2021-08-28]数据结构第1章-线性表Part1

数据结构第1章 - 线性表(Part 1)

写在开头

作为生活中最常见的一种数据结构(嗯?),线性表以其简单和基本的特点被广泛使用,学好线性表非常重要,使用线性表能让我们更灵活地存储数据。

线性表的定义

线性表,LinearList,是由许多相同的数据元素所组成的一个有限序列,由于其存储的线性(这不需要解释吧),被成为线性表。
一个非空的线性表可以这么表示:
L=(a1, a2, …, an )
其中,ai被称为数据元素,i为在这个线性表中的位置
在这里插入图片描述

线性表基本操作

作为一个成熟的数据结构,当然要有好用的增删改查方法啦~ 因此对于一个抽象类型的线性表,我们需要有如下操作

  • Init:初始化一个空的线性表【增】
  • Destory:销毁当前使用的线性表【删】
  • GetLength:获取当前线性表的数据数量【查】
  • GetByIndex:获取指定位置的元素【查】
  • Locate:查找指定元素并返回位置【查】
  • Insert:在指定位置插入一个元素【增】
  • Modify:在指定位置修改元素值【改】
  • Delete:删除指定位置的元素【删】
  • IsEmpty:查询线性表是否为空【查】
  • Print:遍历并输出【查】,个人觉得是遍历+GetByIndex

线性表存储结构1 - 顺序表

顺序表的定义(不正经)

其实哦,线性表非常像一个我们一直用的东西——数组!
其实这个说的拉一点,就是一个开的很大的数组加上一个代表元素数量的变量(考试别这么写!顺序表和数组还是不一样滴)
在这里插入图片描述
因为每个元素的位置在内存里都是线性的(数组就是这么存哒)所以叫线性表啦:
第i个元素内存位置=第一个元素内存位置+(i-1)×每个数据元素所占空间

顺序表的定义(正经)

线性表的顺序存储结构称为顺序表(sequential list)。
顺序表是用一段地址连续的存储单元依次存储线性表的数据元素。由于线性表中每个元素的类型相同,通常用一维数组来实现顺序表,也就是把线性表中相邻的元素存储在数组中相邻的位置,从而导致了数据元素的序号和存放它的数组下标之间的一一对应关系。
——王红梅,《数据结构(C++版)(第二版)》

顺序表代码实现

下面就是线性表的C++实现的大类~

const int MAX_SIZE=256;//按需修改

template<class DataType>
class SeqList {
	public:
		SeqList() {
		//无参构造,创建空顺序表
			this -> length = 0;
		}
		SeqList(DataType data[], int length) {
		//带参数构造,将数据传入
			if(length > MAX_SIZE) {
				throw "illegal size";
			}
			this -> length = length;
			for(int i = 0; i < length; i++) {
				this -> data[i] = data[i];
			}
		}
		~SeqList() {
		//析构函数相当于Destory
		}
		int GetLength() {
		//获取当前线性表的数据数量
			return this -> length;
		}
		DataType GetByIndex(int index) {
		//获取指定位置的元素,这边下标从1开始,需要-1
			index--;
			if(index < 0 || index >= this -> length) {
				throw "index out of bounds";
			}
			return this -> data[index];
		}
		int Locate(DataType s) {
		//查找指定元素并返回位置
			for(int i = 0; i < this -> length; i++) {
				if(data[i] == s) {
					return i + 1;
				}
			}
			return 0;
		}
		void Insert(int index, DataType s) {
		//在指定位置插入一个元素
			if(this -> length >= MAX_SIZE) {
				throw "seqlist is full";
			}
			index--;
			if(index < 0 || index > length) {
				throw "index out of bounds";
			}
			for(int i = length; i > index; i--) {
				this -> data[i] = this -> data[i - 1];
			}
			this -> data[index] = s;
			this -> length++;
		}
		void Modify(int index, DataType m) {
		//从指定位置修改值,这边下标从1开始,需要-1
			index--;
			if(index < 0 || index >= this -> length) {
				throw "index out of bounds";
			}
			this -> data[index] = m;
		}
		void Delete(int index) {
		//删除指定位置的元素
			index--;
			if(index < 0 || index >= length) {
				throw "index out of bounds";
			}
			for(int i = index; i < this -> length - 1;i++) {
				this -> data[i] = this -> data[i + 1];
			}
			this -> length--;
			this -> data[this -> length] = NULL;
		}
		void Print() {
		//遍历顺序表并输出
			for(int i = 0; i < this -> length; i++) {
				cout<<this -> data[i]<<endl;
			}
		}
	private:
		int length;
		DataType data[MAX_SIZE];
};

顺序表代码详解

构造和析构
SeqList() {
//无参构造,创建空顺序表
	this -> length = 0;//设置初始空顺序表长度为0
}
SeqList(DataType data[], int length) {
//带参数构造,将数据传入
	if(length > MAX_SIZE) {//检查初始化大小是不是符合条件
		throw "illegal size";
	}
	this -> length = length;//传入大小
	for(int i = 0; i < length; i++) {//遍历传入的数组
		this -> data[i] = data[i];//传入数据
	}
}
~SeqList() {
//析构函数相当于Destory,销毁顺序表实例
}
查询

查询长度和用位置返回数据比较简单;定位元素则需要一个个的接下去寻找,由于无序也没办法二分,只能使用O(length)的查找方式

int GetLength() {
//获取当前线性表的数据数量
	return this -> length;
}
DataType GetByIndex(int index) {
//获取指定位置的元素,这边下标从1开始,需要-1
	index--;
	if(index < 0 || index >= this -> length) {//检查查询下标是否合法
		throw "index out of bounds";
	}
	return this -> data[index];
}
int Locate(DataType s) {
//查找指定元素并返回位置
	for(int i = 0; i < this -> length; i++) {//顺序查找
		if(data[i] == s) {
			return i + 1;//位置是i + 1
		}
	}
	return 0;
}
插入、修改和删除

插入时,我们需要先把位置空出来再放入数据,由于线性表有空的空间,我们从后往前逐个往后挪,最后将要插入元素插入空挡;
在这里插入图片描述

修改非常简单,就是改一下值;
删除则是插入的反过程,用后面的元素逐个覆盖前面的元素,最后把多出来的一个空清空。
在这里插入图片描述

void Insert(int index, DataType s) {
//在指定位置插入一个元素
	if(this -> length >= MAX_SIZE) {//错误检查:是不是满了
		throw "seqlist is full";
	}
	index--;
	if(index < 0 || index > length) {//错误检查:插入位置是否合法
		throw "index out of bounds";
	}
	for(int i = length; i > index; i--) {//把元素往后挪
		this -> data[i] = this -> data[i - 1];
	}
	this -> data[index] = s;//在空挡插入元素
	this -> length++;//加了一个元素,长度+1
}
void Modify(int index, DataType m) {
//从指定位置修改值,这边下标从1开始,需要-1
	index--;
	if(index < 0 || index >= this -> length) {//检查下标是否合法
		throw "index out of bounds";
	}
	this -> data[index] = m;//简单修改
}
void Delete(int index) {
//删除指定位置的元素
	index--;
	if(index < 0 || index >= length) {//检查下标是否合法
		throw "index out of bounds";
	}
	for(int i = index; i < this -> length - 1;i++) {//往前覆盖
		this -> data[i] = this -> data[i + 1];
	}
	this -> length--;//长度-1
	this -> data[this -> length] = NULL;//把往前挪之后多出来的一个空删掉
}
数据可视化

把数据都输出,应该也算是种可视化吧uwu

void Print() {
//遍历顺序表并输出
	for(int i = 0; i < this -> length; i++) {
		cout<<this -> data[i]<<endl;
	}
}

顺序表小结

记不住就多看几遍,无非是增删改查,自己去试试看吧

写在最后(Part1)

刚开始学习数据结构难免会摸不着头脑,不过顺序表比较简单,试着从简单的数组过渡到线性表中最常见的顺序表会比较轻松,加油~~ 下一章讲线性表的链式存储结构——链表,将会非常好玩。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
线性表是一种常见的数据结构,它表示具有相同数据的一组元素的有序序列。线性表中的元素之间存在一种顺序关系,每个元素都有一个前驱和一个后继(除了第一个元素没有前驱,最后一个元素没有后继)。线性表可以用顺序存储结构或链式存储结构实现。 在顺序存储结构中,线性表的元素按照顺序存储在连续的内存空间中,可以通过元素的下标来访问和操作元素。插入或删除元素时,需要移动其他元素,因此操作的时间复杂度较高。 链式存储结构中,线性表的每个元素都包含一个数据域和一个指针域,指针指向下一个元素。通过指针的链接,元素可以按照任意顺序存储在内存中,插入和删除操作只需要改变指针的指向,因此时间复杂度较低。 线性表常见的操作包括插入、删除、查找、获取长度等。其中插入和删除操作需要注意保持线性表的顺序关系。 常见的线性表数组、链表、栈和队列。数组是最简单的线性表,通过下标可以直接访问元素;链表是动态存储结构,插入和删除操作方便,但访问元素需要遍历链表;栈是一种特殊的线性表,只允许在表的一端进行插入和删除操作;队列也是一种特殊的线性表,只允许在表的一端进行插入操作,在另一端进行删除操作。这些数据结构在实际应用中都有各自的应用场景和优缺点。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值