(顺序容器类)向量应用:一个非常长的整数类

本文探讨了C++中的vector类在实现一个非常长的整数类中的应用,强调了vector自动调整大小、快速随机访问和尾部插入的优势,同时也指出在非尾部插入时效率较低的问题。文章还提到了vector相关的头文件如< vector >、< algorithm >和< ctime >,并提及了一个基于vector的长整数类的头文件very_long_int class.h及其驱动程序test.cpp的测试情况,其中operator*重载和factorial()函数的效率问题被指出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vector类可能的字段:

template <class T>
class vector
{
	T *start;	// 指向分配的数组首地址(初始为 1KB字节)
	T *finish;	// 指向紧随向量最后一项之后的位置
	T *end_of_storage;	// 指向紧随数组占据的最后一个空间之后的位置
};

vector类的一个实现:

vector<double> weights;
weights.push_back(7.3);
// 分配堆中一个存储块(1KB),一个double占据8个字节,就分配了128个double型数组

假设将另外的127个double型插入weights后,finish = end_of_storage意味着分配给weights的当前块用完;


weights.push_back(15.5);
// 如果一个向量对象对应的数组已满且又尝试新的插入,那么这个数组的容量将加倍


对比数组优势:1)可以自动调整大小;2)快速随机访问和尾部插入;

缺点:1)在除尾部之外的单元插入是很慢的(必须移动其他项)


#include <vector>

vector模板类的方法接口:

vector模板类的方法接口:
vector();			// 构造器
vector(const vector<T>& x);	// 拷贝构造器
void push_back(const T& x);	// 在向量尾部插入 X 的拷贝(可看成insert()方法的特例)
iterator insert(iterator position, const T& x);	// 在position所在位置插入 X 的拷贝;
void pop_back();		// 删除向量尾部的项(可看成insert()方法的特例)
iterator erase(iterator position);	// 删除position位置的项
iterator erase(iterator _first, iterator _last); // 删除_first 与 _last 之间的所有项
unsigned size() const;		// 返回向量中项的数量
bool empty() const;		// 向量不包含任何项 ?true : false
T& operator[](unsigned n);	// 返回对向量的从开头算起的第 n 项的引用
iterator begin();		// 返回位于向量开头的迭代器
iterator end();			// 返回恰好位于向量最后一项之后位置的迭代器
T& front();			// 返回对这个向量开头项的引用
T& back();			// 返回对向量尾部项的引用。如果该向量为空,则返回值是未定义的

#include <algorithm>

C++的标准模版库(STL)中最重要的头文件之一,提供了大量基于迭代器的非成员模版函数

void reverse(bidirectionalIterator _first, bidirectionalIterator _last );
// 反转双向迭代器 _first 与 _last 之间元素的顺序

#include <ctime>

long time(long *timer);	// 参数为 NULL时,返回自 1970 年一月 1 日午夜 (00:00) 到系统时钟之间的秒数


(一个非常长的整数类)头文件very_long_int class.h

#ifndef _VERY_LONG_INT
#define _VERY_LONG_INT

#include <iostream>
#include <vector>
#include <algorithm> // reverse()
using namespace std;
/*----------------------------------------
向量应用:高精度算法 -- 非常长的整数的运算
----------------------------------------*/
class very_long_int
{
	vector<char> digits;
public:
//	very_long_int() {}			// 编译器会自动生成
//	very_long_int operator=(const very_long_int& other_very_long);	// 编译器会自动生成
	// 前置条件: n >= 0
	// 后置条件: 返回对象的阶乘
	very_long_int factorial(int n) const;
	very_long_int operator--(int);
	very_long_int operator*(const very_long_int& other_very_long) const;
	very_long_int operator+(const very_long_int& other_very_long) const;
	// 前置条件: 输入一系列char位,遇到 ‘X’ 结束输入;
	//			忽略无效的char、空格和行尾标志;
	// 后置条件: very_long包含非常长的整数
	friend istream& operator>>(istream& in, very_long_int& very_long);
	// 后置条件: 输出very_long
	friend ostream& operator<<(ostream& out, const very_long_int& very_long);
};

#endif

(一个非常长的整数类)类实现very_long_int class.cpp

#include "very_long_int class.h"
/*
very_long_int very_long_int::operator=(const very_long_int& other_very_long)
{
	digits.erase(digits.begin(), digits.end());
	for (int i = 0; i < other_very_long.digits.size(); i++)
		digits.push_back(other_very_long.digits[i]);
	return *this;
}
*/

very_long_int very_long_int::factorial(int n) const
{
	very_long_int temp = *this,
		sum = *this;
	if (n == 0){
		sum.digits.erase(sum.digits.begin(), sum.digits.end());	// 释放sum占用的所有内存
		sum.digits.push_back('0'-'0');	// 分配一个字节存储 0
	}
	else
		for (; n != 1; n--)
			sum = sum * temp;	// 累乘求阶乘
	return sum;
}

very_long_int very_long_int::operator--(int)
{
	if (digits[digits.size()-1] > 0)	// 个位数 > 0
		digits[digits.size()-1]--;
	else	// 个位数 = 0,产生借位
	{
		unsigned bit = 0;	// 向digits[bit]位 借位
		for (unsigned i = 1; i < digits.size(); i++)
			if (digits[digits.size()-1-i] != 0){
				bit = digits.size()-1-i;
				break;
			}
		digits[bit]--;
		for (unsigned i = digits.size()-1; i > bit; i--)
			digits[i] = 9;	// 借位后,低于digits[bit]的所有位 变成9
	}
	if (digits[0] == 0)	// 借位后如果最高位为0,就删除这个最高位
		digits.erase(digits.begin());
	return *this;
}

very_long_int very_long_int::operator*(const very_long_int& other_very_long) const
{
	very_long_int sum = other_very_long;
	very_long_int temp = *this;

	if ((temp.digits.size() == 1 && temp.digits[0] == 0) ||
		(other_very_long.digits.size() == 1 && other_very_long.digits[0] == 0)){
		sum.digits.erase(sum.digits.begin(), sum.digits.end());	// 释放sum占用的所有内存
		sum.digits.push_back('0'-'0');	// 分配一个字节存储 0
	}
	else{
		while (temp.digits.size() != 1 || temp.digits[0] != 1){
			sum = sum + other_very_long;	// 累加求积
			temp--;
		}
	}
	return sum;
}

very_long_int very_long_int::operator+(const very_long_int& other_very_long) const
{
	very_long_int sum;	// 和(返回值)
	int carry = 0,		// 进位值
		small_size,		// *this和other_very_long对象位数较小者
		big_size,		// *this和other_very_long对象位数较大者
		value;			// *this和other_very_long对象位数相加的和
	if (digits.size() > other_very_long.digits.size()){
		big_size = digits.size();
		small_size = other_very_long.digits.size();
	}
	else{
		big_size = other_very_long.digits.size();
		small_size = digits.size();
	}
	vector<char>::const_iterator iter1 = digits.end(),
		iter2 = other_very_long.digits.end();	//const_iterator用于遍历const容器
	for (int i = 0; i < big_size; i++){
		if (i < small_size){
			iter1--; iter2--;
			value = *iter1 + *iter2 + carry;
			carry = value / 10;		// 是否产生进位
			sum.digits.push_back(value % 10);
		}	// 个位数为 sum.digits[0],应为 sum.digits[sum.digits.size()-1];
		else if (big_size == digits.size()){
			iter1--;
			value = *iter1 + carry;
			carry = value / 10;		// 是否产生进位
			sum.digits.push_back(value % 10);
		}
		else if (big_size == other_very_long.digits.size()){
			iter2--;
			value = *iter2 + carry;
			carry = value / 10;		// 是否产生进位
			sum.digits.push_back(value % 10);
		}
	}
	if (carry == 1)		// 是否产生新位
		sum.digits.push_back(carry);
	reverse(sum.digits.begin(), sum.digits.end());	// 反转sum.digits中各元素的顺序
	return sum;
}

istream& operator>>(istream& in, very_long_int& very_long)
{
	very_long.digits.erase(very_long.digits.begin(), very_long.digits.end());
//	cout << "Please enter a very_long_int data, 'X' to quit:\n";	(提示信息在main())
	char ch_temp;
	cin >> ch_temp;		// 忽略空格和行尾标志
	while (ch_temp != 'X'){
		if (ch_temp >= '0' && ch_temp <= '9')
			very_long.digits.push_back(ch_temp-'0'); // 合法字符转换成数字
		cin >> ch_temp;
	}
	while (very_long.digits[0] == 0 && very_long.digits.size() != 1)	// 删除very_long中对应整数前的所有0
		very_long.digits.erase(very_long.digits.begin());
	return in;
}

ostream& operator<<(ostream& out, const very_long_int& very_long)
{
//	cout << "The very_long_int data =\n";	(提示信息在main())
	for (unsigned i = 0; i < very_long.digits.size(); i++)
		cout << (int)very_long.digits[i];
	return out;
}

(一个非常长的整数类)驱动程序test.cpp

#include "very_long_int class.h"
#include <ctime>	// time()
int main()
{
	very_long_int very_long1, very_long2;
	cout << "Please enter a very_long_int data, 'X' to quit:\n";
	cin >> very_long1;
	cout << "Please enter a very_long_int data, 'X' to quit:\n";
	cin >> very_long2;
	cout << "(First):	" << very_long1 << endl
		 << "(Second):	" << very_long2 << endl << endl;

	very_long_int very_long3;
	very_long3 = very_long1 + very_long2;
	cout << "(Third = First + Second):\n" << very_long3 << endl << endl;

	very_long3--;
	cout << "(Third--):\n" << very_long3 << endl << endl;

	long start_time, finish_time;
	start_time = time(NULL);
	cout << "(Fourth = First * Second):\n"
		 << very_long1 * very_long2 << endl;
	finish_time = time(NULL);
	cout << "time = " << finish_time-start_time << " Second.\n\n";

	start_time = time(NULL);
	cout << "(Fifth = First ^ 5):\n"
		 << very_long1.factorial(5) << endl;
	finish_time = time(NULL);
	cout << "time = " << finish_time-start_time << " Second.\n";

	return 0;
}

(一个非常长的整数类)测试:


operator*的重载与 factorial() 是很糟糕的算法,很耗运行时间



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值