数据结构之vector的实现

news2024/11/25 4:18:00

数据结构之vector的实现

Vector类分为:构造函数、析构函数、只读函数、修改函数、私有函数、成员变量(数据区和大小)

# include <iostream>
# include <algorithm>
# include <cstdlib>

# define DEFAULT_CAPACITY 3

template <typename T> struct pp {
	void operator()(T & e) {
		std::cout << e << "\n";
	}
};

void bubbleSort(int * a, int n = 13)
{
	bool isSorted = false;
	for (int i = n - 1; !isSorted && i > 0; --i) // 待排序范围
	{
		isSorted = true;
		for (int j = 0; j < i; ++j) // 从开头到无序的前一个位置
		{
			if (a[j] > a[j + 1])
			{
				std::swap(a[j], a[j + 1]);
				isSorted = false;
			}
		}
	}
	return;
}

template <typename T> class Vector
{
public:
	// 析构函数
	~Vector() { delete []elem; }

	// 构造函数

	Vector(int c = DEFAULT_CAPACITY, int s = 0, T v=0)  // c 容量 s 规模 v 每个元素初始值
	{
		elem = new T[c];
		for (size = 0; size < s; ++size)
		{
			elem[size] = v;
		}
	}


	Vector(const Vector<T> & v) { copyForm(v.elem, 0, Vector.size); }

	Vector(T const * A, int lo, int hi) { copyForm(A, lo, hi); }

	// 运算符重载
	Vector<T>& operator = (const Vector<T> & v) // 
	{
		delete[]elem;
		elem = new T[v.capacity];
		copyFrom(v, 0, v.size);
		return *this;
	}
	T& operator[](int rank)
	{
		return elem[rank];
	}

	//  置乱
	void permute(void)
	{
		for (int i = size - 1; i > 0; --i)
		{
			std::swap(elem[i], elem[rand() % (i + 1)]);
		}
	}

	void unsort(int lo, int hi)
	{
		T * V = elem + lo;
		for (int i = hi - lo - 1; i > 0; --i)
		{
			std::swap(V[i], V[rand() % (i + 1)]);
		}
	}

	// 查找
	int find(T const & e, int lo, int hi)
	{
		for (; hi > lo && e != elem[hi - 1]; hi--);
		return hi;
	}

	// 插入
	void insert(T const & e, int rank)
	{
		expand();
		for (int i = size; i > rank; --i)
		{
			elem[i] = elem[i - 1];
		}
		elem[rank] = e;
		++size;
	}

	// 删除
	void remove(int lo, int hi)
	{
		if (lo == hi) return;
		for (int i = lo; i < size - hi + lo; ++i)
		{
			elem[i] = elem[i + hi - lo];
		}
		size -= hi - lo;
		shrink();
	}

	void remove(int rank)
	{
		remove(rank, rank + 1);
	}

	//  唯一化 返回删了多少个
	int unique(void)
	{
		int oldSize = size;
		for (int i = 0; i < size; ++i)
		{
			if (find(elem[i], i + 1, size)) remove(i);
			size--;
		}
		return oldSize - size;
	}

	// 遍历
	template <typename T2> void traverse(T2 & visit)
	{
		for (int i = 0; i < size; ++i)
		{
			visit(elem[i]);
		}
	}

	//*****************************************************以下是有序向量操作***************************************************

	// 有序性甄别,返回无序对儿数
	int disOrdered(void) const
	{
		int n = 0;
		for (int i = 0; i < size - 1; ++i)
		{
			if (elem[i] > elem[i + 1]) ++n;
		}
		return n;
	}

	// 针对有序vector的唯一化,O(n)
	void unique_ordered(void)
	{
		int i = 0, j = 1;
		while (j < size)
		{
			if (elem[i] == elem[j]) ++j;
			else
			{
				elem[i + 1] = elem[j];
				++i;
				++j;
			}
		}
		size = i + 1;
	}

	// 二分查找,找最靠右的等于e的元素的位置
	int search(const T & e)
	{
		int lo = 0; hi = size;
		while (lo < hi)
		{
			int mi = (lo + hi) / 2;
			if (e < mi) hi = mi;
			else lo = mi + 1;
		}
		return lo-1;
	}

protected:

	int size;
	int capacity;
	T * elem; //数据区

	void copyForm(T const * A, int lo, int hi) // 左开右闭,仅在构造时使用,所以从0开始装
	{
		elem = new T[(hi - lo) * 2];
		capacity = (hi - lo) * 2;
		size = 0;

		while (lo < hi)
		{
			elem[size] = A[lo];
			++size;
			++lo;
		}
	}

	void expand(void)
	{
		if (size < capacity) return;

		if (capacity < DEFAULT_CAPACITY) capacity = DEFAULT_CAPACITY;
		capacity *= 2;

		T * oldElem = elem;
		elem = new T[capacity];

		for (int i = 0; i < size; ++i)
		{
			elem[i] = oldElem[i];
		}
		delete[]oldElem;
		return;
	}

	void shrink(void)
	{
		if (capacity * 1.0 / size > 0.25) return;

		if (capacity < DEFAULT_CAPACITY * 2) capacity = DEFAULT_CAPACITY * 2;
		capacity /= 2;

		T * oldElem = elem;
		elem = new T[capacity];

		for (int i = 0; i < size; ++i)
		{
			elem[i] = oldElem[i];
		}
		delete[]oldElem;
		return;
	}

};
总结·易错篇:
  • 该模板类的类型是Vector<T> 而非 Vector
  • 模板template <typename T>template <class T> 的区别
  • return * this
  • 把elem数组封装为向量的好处:避免野指针,指针指向向量对象,里边包着的永远是有效的elem,若直接指向elem,则随着脱壳,指针无法及时的指向新壳。
  • # define DEFAULT_CAPACITY 3; 不能写分号
    宏定义写分号的报错
  • 非常量引用只能绑定到左值 简言之,临时对象不能寻址。出现这个错误的原因就是进行了强制类型转换+函数引用调用。
总结·效率篇:
  • const 类型名 & 变量名 效率高
  • 代码的重用,比如写operate=()时,可以用写好的copyFrom(),就不用重写详细的复制过程了
  • expand()为什么不重用copyFrom(),因为涉及到capacity的设置,在capacity很小的时候,是直接扩到最小容量,再二倍。
  • 二分查找与Fibonacci查找

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

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

相关文章

数学建模-图论 最短路径

作图 %% 注意&#xff1a;以下代码需要较新版本的matlab才能运行&#xff08;最好是2016版本及以上哦&#xff09; % 如果运行出错请下载新版的matlab代码再运行%% Matlab作无向图 % &#xff08;1&#xff09;无权重&#xff08;每条边的权重默认为1&#xff09; % 函数graph(…

SCT52A40,对标UCC27200、UCC27201半桥驱动IGBT/MOSFET栅极驱动器

特点&#xff1a; • 8-24V宽供电电压 • 驱动高侧和低侧N通道MOSFET • 4A峰值输出源电流和汇电流 • 升压电源电压范围可达120V • 集成阴极负载二极管 • TTL兼容输入&#xff0c;-10V输入 • 45ns传输延迟 • 1000pF负载下7ns上升和4.5ns下降时间 • 2ns延迟匹配时间 • 静…

[centos]安装mysql8.0.26

1、首先&#xff0c;根据自己的机子到MySQL官网下载对应的数据库https://dev.mysql.com/downloads/mysql/ 2、卸载mariadb&#xff0c;并解压Mysql 3、安装 rpm -ivh mysql-community-common-8.0.26-1.el7.x86_64.rpm --nodeps rpm -ivh mysql-community-libs-8.0.26-1.el7.x…

《向量数据库指南》:向量数据库Pinecone快速入门

目录 ⚠️警告 ℹ️注意 ⚠️警告 如何开始使用Pinecone向量数据库。 本指南介绍如何在几分钟内设置Pinecone向量数据库。 安装Pinecone客户端(可选)此步骤是可选的。只有在您想使用Python客户端时才执行此步骤。 使用以下shell命令安装Pinecone: Python pip insta…

potplayer放大画面,画面拖拽。备份

放大画面&#xff1a; 按住alt和鼠标左键&#xff0c;就可以拖动放大后的画面了 窗口化示图

UE4/5AI制作基础AI跳跃(适合新手)

目录 制作 添加逻辑 添加导航链接代理 结果 在上一章中&#xff0c;我们讲解了简单的AI跟随玩家&#xff0c;制作了一个基础的ai。 UE4/5AI制作基础AI&#xff08;适合新手入门&#xff0c;运用黑板&#xff0c;行为树&#xff0c;ai控制器&#xff0c;角色类&#xff0c;任…

TCP实现FTP功能

目录 server client makefile 运行顺序 FTP&#xff08;File Transfer Protocol&#xff09;是一种用于在计算机网络上传输文件的标准协议。 它允许用户通过网络将文件从一个计算机&#xff08;称为FTP服务器&#xff09;传输到另一个计算机&#xff08;称为FTP客户端&…

【Python】pyinstaller全新的打包方案,堪称完善!

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤-*- mode: python ; coding: utf-8 -*-剩下的项就省略了-*- mode: python ; coding: utf-8 -*-用一个函数选择性对依赖文件目标路径改名打印 a.binaries&#xff0c;检查依赖文件目标路径剩下的省略了2. 第二步&#xff…

Taurus .Net Core 微服务开源框架:Admin 插件【4-3】 - 配置管理-Mvc【Plugin-MicroService 微服务】

目录 1、系统配置节点&#xff1a;Mvc - Plugin - MicroService 配置界面&#xff1a;注册中心 2、系统配置节点&#xff1a;Mvc - Plugin - MicroService 配置界面&#xff1a;注册中心&#xff08;从&#xff09; 3、系统配置节点&#xff1a;Mvc - Plugin - MicroService…

代码随香录day21

235. 二叉搜索树的最近公共祖先 本题思路&#xff1a; 还是要利用二叉搜索树的特性&#xff0c;中序遍历为有序数组。如果pq两个节点都小于root&#xff0c;那么最近公共祖肯定是在他的左子树&#xff0c;如果都大于那么&#xff0c;肯定就在右子树。然后直接return root 代码…

C++编程(四) —— OOP

文章目录 前言一、this指针二、构造和析构三、深拷贝浅拷贝浅拷贝深拷贝 编程实践 前言 什么是OOP思想&#xff1f; OOP语言的四大特征&#xff1a; 抽象&#xff0c;封装/隐藏&#xff0c;继承&#xff0c;多态 一、this指针 this指针》类》很多对象 一套成员方法是如何处…

04.MySQL——用户管理

用户管理 用户管理的价值 用户 用户信息 MySQL中的用户&#xff0c;都存储在系统数据库mysql的user表中 use mysql;select host,user,authentication_string from user;host&#xff1a; 表示这个用户可以从哪个主机登陆&#xff0c;如果是localhost&#xff0c;表示只能从…

【贪心算法Part03】| 1005.K次取反后最大化的数组和、134.加油站、135.分发糖果

目录 &#x1f388;LeetCode1005.K次取反后最大化的数组和 &#x1f388;LeetCode134.加油站 &#x1f388;LeetCode135.分发糖果 &#x1f388;LeetCode1005.K次取反后最大化的数组和 链接&#xff1a;1005.K次取反后最大化的数组和 给你一个整数数组 nums 和一个整数 k…

31,list容器

31.1list基本概念 功能&#xff1a;将数据进行链式存储 链表(list)是一种物理存储上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成&#xff1a;链表由一系列结点组成 结点的组成&#xff1a;一个是存储数据元素的数据域&#xf…

【剧前爆米花--web】HTTP协议格式详解以及构造

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaEE初阶》 文章分布&#xff1a;这是一篇关于HTTP协议的文章&#xff0c;在这篇文章中我会说明HTTP协议格式以及相关的构造&#xff0c;希望对你有所帮助&#xff01; 目录 HTTP协议 HTTP协议格式 HTTP请求 HTTP响应详情…

拿了 7 个大厂 offer,我有话说

我有一个朋友&#xff0c;举办了一个分享会。他春招期间收割了阿里、京东、美团、拼多多、网易、腾讯云智等多家公司的实习 offer。 他最近从一家A大厂实习换到了另外一家B大厂实习&#xff0c;分享会长达100分钟&#xff0c; 共解答了 40 多个问题。 我也从中抽取一些比较有共…

一个小技巧,分分钟搞定新零售!

新零售模式的兴起带来了线上线下销售渠道的整合&#xff0c;而自动售货机作为新零售模式的一种重要形式&#xff0c;提供了便捷的自助购物体验。 自动售货机作为新零售模式的一种典型应用&#xff0c;以其便利性、快捷性和24小时无人值守的特点&#xff0c;深受消费者和商家的青…

MySQL数据库 【增删改查】

目录 一、新增 指定列插入 一次插入多个数据 二、查询 1、全列查询 2、指定列查询 3、查询字段为表达式 4、查询的时候给列名/表达式 指定别名 5、查询时去重 6、排序查询 7、条件查询 8、模糊查询 9、空值查询 10、分页查询 三、修改 四、删除 SQL 最核心…

python如何知道你的导包在哪/site-package在哪/anaconda中的模块文件在哪

参考: https://stackoverflow.com/questions/31003994/where-is-site-packages-located-in-a-conda-environment anaconda虚拟环境中的site-package在如下目录&#xff0c;/opt/conda/envs/env_cp37_STAGATE_TF/lib/python3.7/site-packages/。 基于寻找你导包的物理位置在哪…