C++ 线性表、内存操作、 迭代器,数据与算法分离。

news2024/11/22 17:54:30

线性表:

         线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的

一种,一个线性表是n个具有相同特性的数据元素的有限序列。


          线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储,但是把最后一个数据元素的尾指针指向了首位结点)。

线性表_百度百科 (baidu.com)

C++中的数组,vector,string是线性表,大家对线性表操作非常熟悉,感觉非常方便,比如:

std::string s = "Hello World!";

在字符串 s 中的第二个字符是  * (s.c_str() + 1),  或者  *(s.begin() + 1), 是字符 e;

为什么还要设计迭代器,是因为要数据与算法分离,这是C++标准库的核心,如果

不理解这个,你会感觉标准库非常难用,明明很简单的事,为什么搞得那么复杂。

看下面的例子:

int main() {	

	std::string s = "Hello World!";
	std::list<char> slist1 = { 'H','e','l','l','o', ' ', 'W','o','r','l','d','!'};
	std::list<char> slist2(s.begin(), s.end());

	for (auto c : slist1) {
		std::cout << c;
	}

	std::cout << "\n";

	for (auto c : slist2) {
		std::cout << c;
	}

	std::cout << "\n";

	return 0;
}

输出结果都是:

因此,设计迭代器的核心目标数据与算法分离。

再看一个例,关于内存操作的例子,看下面的函数:

 针对线性表:

/// <summary>
/// 不改变原有数据,把内存段区间 [begin,pend) 向后移动nCount位,
/// 如果bFilling为True,则用相应的pFilling所指的数据填充空出来的内存。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="pbegin"></param>
/// <param name="pend"></param>
/// <param name="nCount"></param>
/// <param name="bFilling"></param>
/// <returns></returns>
/// 创建时间:2024-10-03    最后一次修改时间:2024-10-03 (已测度)
template<class T>
T* MoveBack(T* pbegin, T* pend, const size_t& nCount, const bool& bFilling = false,
const T* pFilling = null)
{
	assert(pend >= pbegin);

	for (size_t n = 0; n < pend - pbegin; ++n) {

		*(pend + nCount - 1 - n ) = *(pend - 1 - n);
	}


	if (bFilling && pFilling) { //检查bFilling不能在区间[pbegin,pend + nCount)中

		//assert(pFilling < pbegin || pbegin > pend + nCount);

		for (size_t n = 0; n < nCount; ++n) {

			*(pbegin + n) = *(pFilling + n);
		}
	}

	return pbegin;
}
int main() {	

	std::string s = "Hello World!";

	//线性表
	_Array<char> arr;
	arr.SetBuffer(20,true);	
	arr.Add(s.begin(), s.end());
	for (auto c : arr) {std::cout << c;}
	std::cout << "\n";
	 
	//在线性表中"Hello World!########" => (后移四位)"####Hello World!####
	//前面####用"中国"填空

	std::cout << MoveBack(arr.Begin(), arr.End(), 7, true, "中国 : ") << "\n";



}

运行结果:

下面我们来设计可以针对迭代器进行移动的MoveBack_new函数

  例子后面的???????,是为容器预留下的内存空间。

template<class IterClass, class ValueType = IterClass::value_type>
const IterClass MoveBack_new(const IterClass& itbegin, const IterClass& itend, const size_t& nCount,
	const bool& bFilling = false, const ValueType* pFilling = null)
{
	//assert(itend >= itbegin);

	for (size_t n = 0; n < itend - itbegin; ++n) {

		*(itend + nCount - 1 - n) = *(itend - 1 - n);
	}


	if (bFilling && pFilling) { //检查bFilling不能在区间[pbegin,pend + nCount)中

		//assert(pFilling < pbegin || pbegin > pend + nCount);

		for (size_t n = 0; n < nCount; ++n) {

			*(itbegin + n) = *(pFilling + n);
		}
	}

	return itbegin;
}

执行程序:

int main() {	

	std::string s = "Hello World!???????";

	//线性表
	_Array<char> arr;
	arr.SetBuffer(30,true);	
	arr.Add(s.begin(), s.end());
	for (auto c : arr) {std::cout << c;}
	std::cout << "\n";
	 
	//在线性表中"Hello World!########" => (后移四位)"####Hello World!####
	//前面####用"中国"填空

	MoveBack_new(arr.begin(), arr.end(), 7, true, "中国 : ");
	cout << "线性表移动后内容:";
	for (auto c : arr) { std::cout << c; }
	std::cout << "\n";

 
	//链表
	_list<char> li;
	li.Add(s.begin(), s.end());
	for (auto c : li) { std::cout << c; }
	std::cout << "\n";



	MoveBack_new(li.begin(), li.begin() + 12, 7, true, "中国 : ");
	cout << "链表移动后内容::";
	for (auto c : li){	std::cout << c;	}
}

执行结果:

结论:

         迭代器设计的目的就是把算法和数据剥离出来,比如上面的MoveBack_new,

即可以对线性表操作,又可以对链表操作,缺点是,在这后面,你要做夶多的工作

和优化,但是这对你熟悉和使用,甚至设计标准库,非常有用。


    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2186327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu2404安装

Ubuntu是一款非常优秀的发行版本&#xff0c;起初她的优势主要在于桌面版&#xff0c;但是随着Centos 从服务版的支持的退出&#xff0c;Ubuntu server也在迅猛的成长&#xff0c;并且不断收获了用户&#xff0c;拥有了一大批忠实的粉丝。好了&#xff0c;废话不多说&#xff0…

基于SSM的出租车租赁管理系统的设计与实现

文未可获取一份本项目的java源码和数据库参考。 1 选题的背景 现代社会&#xff0c;许多个人、家庭&#xff0c;因为生活、工作方式的改变&#xff0c;对汽车不再希望长期拥有&#xff0c;取而代之的是希望汽车能“召之即…

CSS 实现楼梯与小球动画

CSS 实现楼梯与小球动画 效果展示 CSS 知识点 CSS动画使用transform属性使用 页面整体布局 <div class"window"><div class"stair"><span style"--i: 1"></span><span style"--i: 2"></span>…

Flask-3

文章目录 ORMFlask-SQLAlchemySQLAlchemy中的session对象数据库连接设置常用的SQLAlchemy字段类型常用的SQLAlchemy列约束选项 数据库基本操作模型类定义 数据表操作创建和删除表 数据操作基本查询SQLAlchemy常用的查询过滤器SQLAlchemy常用的查询结果方法多条件查询分页器聚合…

Rstudio:强大的R语言集成开发环境(IDE)

Rstudio 应该是 R 语言使用的标配&#xff0c;尽管 Rstudio 的母公司 Posit 推出了新一代的集成开发环境 Positron&#xff0c;但其还处于开发阶段。作为用户不妨让其成熟后再使用&#xff0c;现阶段还是 Rstudio 更稳定。 如果你在生物信息学或统计学领域工作&#xff0c;R语言…

C初阶(六)--- static 来喽

前言&#xff1a;C语言中有许多关键字&#xff08;关键字是预先保留的标识符&#xff0c;具有特殊意义&#xff0c;不能用作变量 名、函数名等普通标识符。&#xff09; 比如&#xff1a;前面在变量与常量那一节提到的extern 就是一个关键字&#xff0c;应该还记得e…

开源项目 - 交通工具检测 yolo v3 物体检测 单车检测 车辆检测 飞机检测 火车检测 船只检测

开源项目 - 交通工具检测 yolo v3 物体检测 单车检测 车辆检测 飞机检测 火车检测 船只检测 开源项目地址&#xff1a;https://gitcode.net/EricLee/yolo_v3 示例&#xff1a;

点云补全 学习笔记

目录 Depth completion with convolutions and vision transformers 依赖项&#xff1a; DCNv2 softpoolnet Depth completion with convolutions and vision transformers Zhang, Y., Guo, X., Poggi, M., Zhu, Z., Huang, G., Mattoccia, S.: Completionformer: Depth co…

JS进阶 3——深入面向对象、原型

JS 进阶3——深入面向对象、原型 1.编程思想 面向过程&#xff1a;分析出解决问题的过程&#xff0c;然后用函数将这些步骤一步步封装起来面向对象&#xff1a;将事物分为一个个对象&#xff0c;然后对象之间分工合作 2.构造函数&#xff1a;封装性、面向对象 构造函数方法存…

Python画笔案例-074 绘制轮子走了

1、绘制轮子走了 通过 python 的turtle 库绘制 轮子走了,如下图: 2、实现代码 绘制轮子走了,以下为实现代码: """轮子走了.py """ import time import turtle def draw_polygon(number,length):

Spark读取MySQL优化方案辩证

0、背景 上篇文章《Spark 任务需要的内存跟哪些因素有关》验证 Spark 任务需要的内存&#xff0c;跟单个 partition 的数据量大小&#xff0c;以及数据计算逻辑复杂度有关。但是之中有个最大的特点&#xff0c;就是把 MySQL 作为数据源的时候&#xff0c;无论数据量多大&#…

【C++】set容器和map容器的基本使用

一、序列式容器和关联式容器 1、STL中的部分容器如&#xff1a;string、vector、list、deque、array、forward_list等&#xff0c;这些容器统称为序列式容器&#xff0c;因为逻辑结构为线性序列的数据结构&#xff0c;两个位置存储的值之间一般没有紧密的关联关系&#xff0c;…

数据结构双向链表和循环链表

目录 一、循环链表二、双向链表三、循环双向链表 一、循环链表 循环链表就是首尾相接的的链表&#xff0c;就是尾节点的指针域指向头节点使整个链表形成一个循环&#xff0c;这就弥补了以前单链表无法在后面某个节点找到前面的节点&#xff0c;可以从任意一个节点找到目标节点…

Leetcode 540. 有序数组中的单一元素

1.题目基本信息 1.1.题目描述 给你一个仅由整数组成的有序数组&#xff0c;其中每个元素都会出现两次&#xff0c;唯有一个数只会出现一次。 请你找出并返回只出现一次的那个数。 你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。 1.2.题目地址 https:…

大语言模型入门(二)——提示词

一、什么是提示词 大语言模型&#xff08;LLM&#xff09;的提示词&#xff08;Prompt&#xff09;是与模型交互的关键&#xff0c;它影响着模型的输出结果。提示词&#xff08;Prompt&#xff09;和提示工程&#xff08;Prompt Engineering&#xff09;密切相关。什么又是提示…

详解代理服务器及Squid

一、 代理服务器简介 &#xff08;1&#xff09;什么是代理服务器 代理服务器英文全称为ProxyServer&#xff0c;其主要功能代理网络用户获取网络信息&#xff0c;起到内网和Internet的桥梁作用。 在TCP/IP网络中&#xff0c;传统的通信过程是这样的&#xff1a;客户端向服务…

ROS2 22.04 Carttographer安装

安装环境&#xff1a; Ubuntu22.04 ros2 humble # 下载源文件 git clone https://github.com/ros2/cartographer.git -b ros2 git clone https://github.com/ros2/cartographer_ros.git -b ros2# 使用小鱼一键配置rosdep wget http://fishros.com/install -O fishros &&am…

基于SSM的本科生操行评定管理系统

文未可获取一份本项目的java源码和数据库参考。 1课题名称 基于SSM的本科生操行评定系统 1.2课题来源和选题依据 随着时代的进步和国民生活水平的不断提高&#xff0c;教育也越来越被人们所重视&#xff0c;学校应该培养品学兼优的全方位人才&#xff0c;学生的行为习惯和日…

mac安装redis实践和客户端连接失败问题解决

文章目录 参考文档和网址redis和客户端安装下载Homebrew程序Mac系统设置redis后台运行设置连接密码安装ARDM使用ARDM连接redis错误解决 参考文档和网址 redis官网命令指导文档brew官网地址brew客户端下载地址redis客户端下载地址 redis和客户端安装 下载Homebrew程序 HomeB…

golang grpc进阶

protobuf 官方文档 基本数据类型 .proto TypeNotesGo Typedoublefloat64floatfloat32int32使用变长编码&#xff0c;对于负值的效率很低&#xff0c;如果你的域有可能有负值&#xff0c;请使用sint64替代int32uint32使用变长编码uint32uint64使用变长编码uint64sint32使用变长…