ACM模板一:线性表、栈、队列、背包

目录

〇,全文说明、宏定义代码

一,输入输出

1,代码

2,测试代码

二,单vector操作

1,代码

2,测试代码

三,Vector拆分拼接、择优合并

1,代码

2,测试代码

四,vector的索引、数据域拓展和提取、拓展排序、逆置换

1,代码

2,测试代码

五,vector的计算

1,代码

2,测试代码

六,单链表

1,代码

2,测试代码

七,双向循环链表

1,代码

2,测试代码

八,STL操作封装、拓展数据结构

1,代码

2,测试代码

九,单调栈、单调队列、背包

1,代码

2,测试代码


〇,全文说明、宏定义代码

类里面和宏定义处都有接口注释,因为宏不体现具体参数,所以注释以类里面的为准。

代码工程结构:

  • 每一章的第一节《代码》可以独立编译运行(本地要加LOCAL宏)
  • 每一章的第二节《测试代码》搭配第〇章的代码和本章第一节的代码可以编译运行并测试成功
  • 所有模板文章的第〇章的代码和其他章第一节的《代码》全部汇总起来可以编译运行

宏定义代码:

#define LOCAL //力扣不要本行代码,其他OJ随意

///(1)输入输出///
#define Print(x) cout << endl << #x << " = "; INOUT::print(x);//输出数据
#define Read(x) INOUT::read(x);//读入数据

///(2)单vector操作///
#define Frev SingleVectorOpt::frev//翻转vector、翻转二维vector的每一行
#define Foverturn SingleVectorOpt::foverturn//沿主对角线(左上角到右下角)翻转二维vector
#define Frotation SingleVectorOpt::frotation//顺时针旋转二维vector
#define DeletAllX SingleVectorOpt::deletAllX//从vector(一维或2维)中删除所有的x
#define DeleteNeiborSame SingleVectorOpt::deleteNeiborSame// 去掉相邻重复元素
#define GetDifNum SingleVectorOpt::getDifNum//判断数组去掉相邻重复数之后有多少个不同的数
#define Fcheng SingleVectorOpt::fcheng//vector乘一个数
#define Fjia SingleVectorOpt::fjia//vector加一个数
#define SortEveryLine SingleVectorOpt::sortEveryLine//二维数组每一行排序
#define FirstInLeft SingleVectorOpt::firstInLeft//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
#define Fminlef SingleVectorOpt::fminlef//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
#define Fminlef2 SingleVectorOpt::fminlef2//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
#define Fmaxlef SingleVectorOpt::fmaxlef//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
#define Fmaxlef2 SingleVectorOpt::fmaxlef2//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
#define Fminrig SingleVectorOpt::fminrig//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
#define Fminrig2 SingleVectorOpt::fminrig2//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
#define Fmaxrig SingleVectorOpt::fmaxrig//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
#define Fmaxrig2 SingleVectorOpt::fmaxrig2//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
#define SplitAtHalf SingleVectorOpt::splitAtHalf//求任意段和的中分位置

///(3)vector拆分拼接、择优合并///
#define FvecJoin VectorJoin::fvecJoin //2个vector(一维或2维)左右拼接起来
#define VecSplit VectorJoin::vecSplit//把v分成前面k个和后面的v.size()-k个,返回拆出来的后面的数组,v本身只留k个
#define LoopSplit VectorJoin::loopSplit//把{1,2,3,4,5,6,7}循环拆分成{1,4,7}{2,5}{3,6}
#define CrossChange VectorJoin::crossChange//交叉交换,v1分成前面k1个和后面的v1.size()-k1个,v2同理,交换后面的2段
#define MergeVector VectorJoin::mergeVector //vector的择优合并
#define FoldJoin VectorJoin::foldJoin//二维vector拼接转化成一维的
#define SelfCopyJoin VectorJoin::selfCopyJoin//把vector自复制一份,前后拼接起来

///(4)vector的索引、数据域拓展和提取、拓展排序、逆置换///
#define Fshr VectorOpt::fshr//收缩计数,把[1 4 4 1]变成[(1,2)(4,2)]或[(1,1)(4,2)(1,1)]
#define Funshr VectorOpt::funshr//平摊,把 [(1,2)(4,2)]变成[1 1 4 4]
#define Fforeach VectorOpt::fforeach//生成枚举序号
#define ChangeMeiJu VectorOpt::changeMeiJu//根据各数字对应的替换列表,生成各种替代枚举
#define SubMeiJu VectorOpt::subMeiJu //根据各id对应的替换列表,生成各种替代枚举
#define ExpandWithId VectorOpt::expandWithId //拓展数据域,加上id
#define SortWithId VectorOpt::sortWithId//给vector拓展,加上id并拓展成稳定排序
#define SortWithOrderMatch VectorOpt::sortWithOrderMatch//给vector拓展,加上id,但只按照原数据进行排序
#define SortId VectorOpt::sortId//排序后数组中的每个数的原ID,输入8 5 6 7,输出1 2 3 0
#define SortId2 VectorOpt::sortId2//每个数在排序后的数组中的ID,输入8 5 6 7,输出3 0 1 2
#define SortExtend VectorOpt::sortExtend//给v排序,v2按照同样的顺序调整,输入{1,3,2}{4,5,6},输出{1,2,3}{4,6,5}
#define FindSum VectorOpt::findSum//2个vector中寻找和为s的对,返回结果的每一行都是[id1,id2]
#define CmpVector VectorOpt::cmpVector//vector的字典序比较,v1<v2是true,v1>=v2是false
#define SortVector VectorOpt::sortVector//vector的字典序排序

///(5)vector的计算///
#define VecAdd VectorCal::vecAdd//2个vector相加
#define EverySum VectorCal::everySum//枚举2个vector的两数之和
#define VecIsSame VectorCal::vecIsSame//判断2个vector(一维或二维)是否全等
#define DeleteSameLine VectorCal::deleteSameLine//二维数组去掉重复行
#define HaveSameData VectorCal::haveSameData//判断vector中是否含有重复元素
#define DeleteLineWithSameDatas VectorCal::deleteLineWithSameDatas//删除二维vector中,含有重复元素的行
#define VecConvolution VectorCal::vecConvolution//2个vector的卷积

///(6)单链表///
#define InitLinkList LinkList::initLinkList//构建链表
#define OutLinkList LinkList::outLinkList//打印链表
#define LinkGetLength LinkList::linkGetLength//获取链表长度
#define IsSameLinkList LinkList::isSameLinkList//两个链表的数据是否全等
#define LinkReverse LinkList::linkReverse//链表反转,返回新的head
#define GetKthFromEnd LinkList::getKthFromEnd//链表中倒数第k个节点
#define GetTail LinkList::getTail//链表最后一个节点
#define LinkSplit LinkList::linkSplit//留下前k个节点,把后面的切下来并返回
#define LinkMerge LinkList::linkMerge//直接合并2个链表
#define MergeTwoLists LinkList::mergeTwoLists//把两个链表交叉合并为一个链表
#define MergeTwoUpLists LinkList::mergeTwoUpLists//把两个升序的链表合并为一个升序的链表
#define ListToVec LinkList::listToVec//把链表转化成结构体指针数组
#define VecToList LinkList::vecToList//把结构体指针数组转化成链表
#define SortLinkList LinkList::sortLinkList//链表排序
#define GetAnyoneInCycle LinkList::getAnyoneInCycle//求链表环中任意节点,没环返回NULL
#define GetCycleLen LinkList::getCycleLen//求链表环的长度,没环返回0
#define GetFirstInCycle LinkList::getFirstInCycle//求链表环的第一个节点,没环返回NULL

///(7)双向循环链表///
#define GetSingleDeList DeLinkList::getSingleDeList//创建单节点双向循环链表
#define MergeDelist DeLinkList::mergeDelist//合并双向循环链表
#define GetLengthOfDeLL DeLinkList::getLengthOfDeLL//获取链表长度

///(8.1)STL操作封装
#define VecGet StlBasicOpt::vecGet//获取列表某处的值
#define Finsert StlBasicOpt::finsert//id处覆盖或者添加一个数
#define DelOnlyOne StlBasicOpt::delOnlyOne//multi***容器x删除一个数值n
#define DelEnd StlBasicOpt::delEnd//删除最后一个元素

///(8.2)拓展数据结构///
// MinMaxStack 略。栈的拓展,支持获取最值,所有接口时间复杂度都是 O(1)
// MinMaxStack2 略。栈的拓展,支持删除最值,所有接口时间复杂度都在 O(log n)之内
// MinMaxQueue 略。队列的拓展,支持获取最值,所有接口的均摊时间复杂度都是O(1)
// QueueWithNoSameData 略。不含重复元素的队列

///(9)单调栈、单调队列、背包///
// MonotonicStack 略。单调栈
// MonotonicQueue 略。单调队列
// Pack 略。01背包、完全背包、多重背包、混合背包
// PackDoubleVolume 略。双代价背包
// PackGroup 略。分组背包
// PackGeneralize 略。泛化物品背包
// PackDepend 略。依赖背包(仅限森林)

一,输入输出

1,代码


//对输入输出进行了封装,利用重载让各种数据结构的输入输出都可以用统一的函数名,同时让输入和输出匹配。
//注意顺序是:基本数据类型、不含容器的自定义数据结构、容器、含容器的自定义数据结构。
const float theNan = 0.123456;  //float默认输出只有6位
class INOUT
{
public:
	//(1)基本类型
	template<typename T>
	static inline void print(T x)
	{
		cout << x << " ";
	}
	template<typename T>
	static inline void read(T& x)
	{
		while (!(cin >> x)) { // only cin type T, ignore other info
			cin.clear();
			cin.ignore();
		}
	}
	static void print(float x)
	{
		if (std::isnan(x)) cout << theNan << " ";
		else cout << x << " ";
	}
	static void read(float& x)
	{
		read<float>(x);
		if (x == theNan) x = NAN;
	}
	// (2)不含容器的自定义数据结构
	//(3)容器
	template<typename T1, typename T2>
	static inline void print(const std::pair<T1, T2>& p)
	{
		print(p.first);
		print(p.second);
	}
	template<typename T1, typename T2>
	static inline void print(const map<T1, T2>& aMap)
	{
		cout << " size = " << aMap.size() << endl;
		for (auto& it : aMap) {
			print(it);
			cout << endl;
		}
	}
	template<typename T>
	static inline void print(const vector<T>& vec)
	{
		cout << " size = " << vec.size() << endl;
		for (auto& it : vec) {
			print(it);
		}
		cout << endl;
	}
	template<typename T1, typename T2>
	static inline void read(std::pair<T1, T2>& p)
	{
		read(p.first);
		read(p.second);
	}
	template<typename Tkey, typename Tvalue>
	static void read(std::map<Tkey, Tvalue>& aMap)
	{
		int num;
		read(num);
		std::pair<Tkey, Tvalue> p;
		while (num--) {
			read(p);
			aMap[p.first] = p.second;
		}
	}
	template<typename T>
	static inline void read(vector<T>& vec)
	{
		int num;
		read(num);
		vec.resize(num); // 慎用
		for (int i = 0; i < num; i++) {
			read(vec[i]);
		}
	}
	//(4)含容器的自定义数据结构
};

2,测试代码

bool testInOut()
{
	vector<int>v;
	// Read(v); // 输入3 100 200 300
	// Print(v); // 输出"v =  size = 3 \n  100 200 300"
	return true;
}

int main()
{
	if (testInOut())cout << "test succ!";
	return 0;
}

二,单vector操作

1,代码

class SingleVectorOpt 
{
public:
    //翻转vector、翻转二维vector的每一行
	template<typename T>
	static vector<T> frev(const vector<T>& v)
	{
		vector<T> ans;
		ans.resize(v.size());
		for (int i = 0; i < v.size(); i++)ans[i] = v[v.size() - 1 - i];
		return ans;
	}
	template<typename T>
	static vector<vector<T>> frev(const vector<vector<T>>& v)
	{
		vector<vector<T>>ans;
		for (int i = 0; i < v.size(); i++)ans.push_back(frev(v[i]));
		return ans;
	}
	//沿主对角线(左上角到右下角)翻转二维vector
	template<typename T>
	static vector<vector<T>> foverturn(const vector<vector<T>>& v)
	{
		vector<vector<T>> ans(v[0].size());
		for (int i = 0; i < v[0].size(); i++) {
			ans[i].resize(v.size());
			for (int j = 0; j < v.size(); j++)ans[i][j] = v[j][i];
		}
		return ans;
	}
	//顺时针旋转二维vector
	template<typename T>
	static vector<vector<T>> frotation(const vector<vector<T>>& v)
	{
		return frev(foverturn(v));
	}
	//从vector(一维或2维)中删除所有的x
	template<typename T>
	static void deletAllX(vector<T>& v, T x)
	{
		for (int i = 0; i < v.size(); i++)if (v[i] == x)v.erase(v.begin() + i--);
	}
	template<typename T>
	static void deletAllX(vector<vector<T>>& v, T x)
	{
		for (auto& vi : v)deletAllX(vi, x);
	}
    // 去掉相邻重复元素
    template<typename T>
    static void deleteNeiborSame(vector<T>&v) 
    {
	    v.erase(std::unique(v.begin(), v.end()), v.end());
    }
	//判断数组去掉相邻重复数之后有多少个不同的数
	template<typename T>
    static int getDifNum(const vector<T>&v)
    {
	    auto v2 = v;
	    deleteNeiborSame(v2);
	    return v2.size();
    }
	//vector乘一个数
	template<typename T1, typename T2>
	static void fcheng(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] *= n;
	}
	//vector加一个数
	template<typename T1, typename T2>
	static void fjia(vector<T1>& v, T2 n)
	{
		for (int i = v.size() - 1; i >= 0; i--)v[i] += n;
	}
	//二维数组每一行排序
	template<typename T>
	static void sortEveryLine(vector<vector<T>>& v)
	{
		for (int i = 0; i < v.size(); i++)sort(v[i].begin(), v[i].end());
	}
	//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
	template<typename T, class P>
	static inline vector<int>firstInLeft(vector<T>v, P pr)
	{
		vector<int> ans;
		if (v.size() == 0)return ans;
		stack<T>st;
		st.push(0);
		ans.push_back(-1);
		for (int i = 1; i < v.size(); i++) //代码用单调栈实现,时间复杂度为O(n)
		{
			while (!st.empty() && !pr(v[st.top()], v[i]))st.pop();
			if (st.empty())ans.push_back(-1);
			else ans.push_back(st.top());
			st.push(i);
		}
		return ans;
	}

	//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a < b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fminlef2(vector<T> v)
	{
		return firstInLeft(v, [](T a, T b) {return a <= b; });  //可换为自定义函数
	}
	//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef(v);
		return ans;
	}
	//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
	template<typename T>
	static vector<int> fmaxlef2(vector<T> v)
	{
		fcheng(v, -1);
		vector<int>ans = fminlef2(v);
		return ans;
	}

	//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fminrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fminlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
	template<typename T>
	static vector<int> fmaxrig2(vector<T> v)
	{
		vector<int>v1 = frev(v), v2 = fmaxlef2(v1);
		fcheng(v2, -1);
		fjia(v2, v.size() - 1);
		return frev(v2);
	}
	// v中都是非负数,对于v的任意一段[low,high],求满足[low,id]总和大于等于[low,high]总和的一半的最小id
	map<int, map<int, int>> splitAtHalf(vector<int>& v)
	{
		vector<int>s;
		int n = 0;
		s.push_back(n);
		for (auto x : v) {
			n += x;
			s.push_back(n);
		}
		map<int, map<int, int>>ans;
		for (int i = 0; i < v.size(); i++) {
			int id = i;
			for (int j = i; j < v.size(); j++) {
				while (s[id + 1] - s[i] < s[j + 1] - s[id + 1])id++;
				ans[i][j] = id;
			}
		}
		return ans;
	}
};

2,测试代码


//2个vector(一维或2维)左右拼接起来
template<typename T>
static vector<T> fvecJoin(const vector<T>& v1, const vector<T>& v2)
{
	vector<T>ans(v1.size() + v2.size());
	copy(v1.begin(), v1.end(), ans.begin());
	copy(v2.begin(), v2.end(), ans.begin() + v1.size());
	return ans;
}
//二维vector拼接转化成一维的
template<typename T>
static vector<T> foldJoin(const vector<vector<T>>& v)
{
	vector<T>ans;
	for (auto& vi : v)ans = fvecJoin(ans, vi);
	return ans;
}

template<typename T>
static bool IsSame(const T &a, const T &b)
{
	return a == b;
}
template<typename T>
static bool IsSame(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() - v2.size())return false;
	for (int i = 0; i < v1.size(); i++)if (!IsSame(v1[i], v2[i]))return false;
	return true;
}
template<typename T, typename T2>
static bool IsSame(const pair<T,T2>&p1, const pair<T, T2>&p2)
{
	return IsSame(p1.first, p2.first) && IsSame(p1.second, p2.second);
}

#define EXPECT_EQ(a,b) if(!IsSame(a,b)){cout<<"ERROR!!!!!!!!!\n";return false;}

bool testSingleVectorOpt()
{
	vector<int>v4{ 3,6 };
	EXPECT_EQ(Frev(v4), (vector<int>{6, 3}));
	vector<vector<char>> v{ {'a','b'},{'c','0'} };
	EXPECT_EQ(foldJoin(v), (vector<char>{ 'a', 'b', 'c', '0' }));
	EXPECT_EQ(foldJoin(Foverturn(v)), (vector<char>{ 'a', 'c', 'b', '0' }));
	EXPECT_EQ(foldJoin(Frotation(v)), (vector<char>{ 'c', 'a', '0', 'b' }));
	DeletAllX(v, '0');
	EXPECT_EQ(foldJoin(v), (vector<char>{ 'a', 'b', 'c'}));
	vector<int>v2{ 1,2,2,3,4,5,5,6 };
	EXPECT_EQ(GetDifNum(v2), 6);
	Fcheng(v2, 2);
	Fjia(v2, 1);
	EXPECT_EQ(v2, (vector<int>{3, 5, 5, 7, 9, 11, 11, 13}));
	v[1].push_back('a');
	EXPECT_EQ(foldJoin(v), (vector<char>{ 'a', 'b', 'c', 'a'}));
	SortEveryLine(v);
	EXPECT_EQ(foldJoin(v), (vector<char>{ 'a', 'b', 'a', 'c'}));
	vector<int>v3{ 1,3,5,2,4 };
	EXPECT_EQ(Fminlef(v3), (vector<int>{-1, 0, 1, 0, 3}));
	return true;
}

int main()
{
	if (testSingleVectorOpt())cout << "test succ!";
	return 0;
}

三,Vector拆分拼接、择优合并

1,代码

class VectorJoin
{
public:
	//2个vector(一维或2维)左右拼接起来
	template<typename T>
	static vector<T> fvecJoin(const vector<T>& v1, const vector<T>& v2)
	{
		vector<T>ans(v1.size() + v2.size());
		copy(v1.begin(), v1.end(), ans.begin());
		copy(v2.begin(), v2.end(), ans.begin() + v1.size());
		return ans;
	}
	template<typename T>
	static vector<vector<T>> fvecJoin(const vector<vector<T>>& v1, const vector<vector<T>>& v2)
	{
		vector<vector<T>>ans(v1.size());
		for (int i = 0; i < v1.size(); i++)ans[i] = fvecJoin(v1[i], v2[i]);
		return ans;
	}
	//把v分成前面k个和后面的v.size()-k个,返回拆出来的后面的数组,v本身只留k个
	template<typename T>
	static vector<T> vecSplit(vector<T>& v, int k)
	{
		vector<T>v2;
		v2.resize(v.size() - k);
		copy(v.begin() + k, v.end(), v2.begin());
		v.resize(k);
		return v2;
	}
	//把{1,2,3,4,5,6,7}循环拆分成{1,4,7}{2,5}{3,6}
	template<typename T>
	static vector<vector<T>> loopSplit(vector<T>& v, int num)
	{
		vector<vector<T>>v2(num);
		for (int i = 0; i < v.size(); i++)v2[i % num].push_back(v[i]);
		return v2;
	}
	//交叉交换,v1分成前面k1个和后面的v1.size()-k1个,v2同理,交换后面的2段
	template<typename T>
	static void crossChange(vector<T>& v1, vector<T>& v2, int k1, int k2)
	{
		vector<T>v3 = vecSplit(v1, k1), v4 = vecSplit(v2, k2);
		v1 = fvecJoin(v1, v4), v2 = fvecJoin(v2, v3);
	}
	//vector的择优合并
	template<typename T>
	static vector<T> mergeVector(const vector<T>& a, const vector<T>& b)
	{
		vector<T> ans;
		int i;
		for (i = 0; i < a.size() && i < b.size(); i++) {
			if (isGreater(a[i], b[i]))ans.push_back(a[i]);
			else ans.push_back(b[i]);
		}
		for (; i < a.size(); i++)ans.push_back(a[i]);
		for (; i < b.size(); i++)ans.push_back(b[i]);
		return ans;
	}
	//二维vector拼接转化成一维的
	template<typename T>
	static vector<T> foldJoin(const vector<vector<T>>& v)
	{
		vector<T>ans;
		for (auto& vi : v)ans = fvecJoin(ans, vi);
		return ans;
	}
	//把vector自复制一份,前后拼接起来
	template<typename T>
	static vector<T> selfCopyJoin(const vector<T>& v)
	{
		return fvecJoin(v, v);
	}
private:
	template<typename T>
	static bool isGreater(T a, T b)
	{
		return a > b;
	}
};

2,测试代码


template<typename T>
static bool IsSame(const T &a, const T &b)
{
	return a == b;
}
template<typename T>
static bool IsSame(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() - v2.size())return false;
	for (int i = 0; i < v1.size(); i++)if (!IsSame(v1[i], v2[i]))return false;
	return true;
}
template<typename T, typename T2>
static bool IsSame(const pair<T,T2>&p1, const pair<T, T2>&p2)
{
	return IsSame(p1.first, p2.first) && IsSame(p1.second, p2.second);
}

#define EXPECT_EQ(a,b) if(!IsSame(a,b)){cout<<"ERROR!!!!!!!!!\n";return false;}


bool testVectorJoin()
{
	EXPECT_EQ(FvecJoin(vector<int>{ 1, 2, 3 }, vector<int>{ 3, 5 }), (vector<int>{1, 2, 3, 3, 5}));
	vector<int>v{ 2,2,4,7 }, v2{ 3,1,3,5 };
	auto v3 = VecSplit(v, 3);
	EXPECT_EQ(v, (vector<int>{2, 2, 4}));
	EXPECT_EQ(v3, (vector<int>{7}));
	v3 = MergeVector(v, v2);
	EXPECT_EQ(v3, (vector<int>{3, 2, 4, 5})); //{2, 2, 4}和{ 3,1,3,5 }  -> {3, 2, 4, 5}
	v3 = SelfCopyJoin(v3);
	EXPECT_EQ(v3, (vector<int>{3, 2, 4, 5, 3, 2, 4, 5}));
	auto v4 = LoopSplit(v3, 3);
	EXPECT_EQ(FoldJoin(v4), (vector<int>{3, 5, 4, 2, 3, 5, 4, 2 }));
	CrossChange(v2, v3, 2, 3);
	EXPECT_EQ(v2, (vector<int>{3, 1, 5, 3, 2, 4, 5}));
	EXPECT_EQ(v3, (vector<int>{3, 2, 4, 3, 5}));
	return true;
}

int main()
{
	if (testVectorJoin())cout << "test succ!";
	return 0;
}

四,vector的索引、数据域拓展和提取、拓展排序、逆置换

1,代码

class VectorOpt
{
public:
	//收缩计数,把[1 4 4 1]变成canSort ? [(1,2)(4,2)] : [(1,1)(4,2)(1,1)]
	template<typename T>
	static vector<pair<T, int>> fshr(vector<T>v, bool canSort = true) //谨慎传引用
	{
		vector<pair<T, int>>ans;
		if (v.size() == 0)return ans;
		if (canSort)sort(v.begin(), v.end());
		int low = 0;
		for (int i = 1; i <= v.size(); i++) {
			if (i == v.size() || v[i] != v[i - 1]) {
				ans.push_back(make_pair(v[i - 1], i - low));
				low = i;
			}
		}
		return ans;
	}
	//平摊,把 [(1,2)(4,2)]变成[1 1 4 4]
	template<typename T>
	static vector<T> funshr(vector<pair<T, int>>& v)
	{
		vector<T>ans;
		for (auto p : v) {
			for (int i = 0; i < p.second; i++)ans.push_back(p.first);
		}
		return ans;
	}
	//生成枚举序号
	template<typename T>
	static vector<vector<int>> fforeach(const vector<vector<T>>& v)
	{
		int s = 1;
		for (auto& vi : v)s *= vi.size();
		vector<vector<int>> ans;
		while (s--)
		{
			vector<int> vt;
			int st = s;
			for (int j = v.size() - 1; j >= 0; j--)
			{
				vt.insert(vt.begin(), st % v[j].size());
				st /= v[j].size();
			}
			ans.push_back(vt);
		}
		return ans;
	}
	//根据各数字对应的替换列表,生成各种替代枚举
	template<typename T>
	static vector<vector<T>> changeMeiJu(const vector<T>& data, map<T, vector<T>>options)
	{
		vector<vector<T>> ans(1, data);
		int len = data.size();
		for (int i = 0; i < len; i++) {
			int s = ans.size();
			for (int j = 0; j < s; j++)for (auto op : options[data[i]]) {
				vector<T> x = ans[j];
				x[i] = op;
				ans.push_back(x);
			}
		}
		return ans;
	}
	//根据各id对应的替换列表,生成各种替代枚举
	template<typename T>
	static vector<T> subMeiJu(const T &data, int len, map<int, T>options)
	{
		vector<T> ans;
		ans.push_back(data);
		for (int i = 0; i < len; i++) {
			int s = ans.size();
			for (int j = 0; j < s; j++)for (auto op : options[i]) {
				T x = ans[j];
				x[i] = op;
				ans.push_back(x);
			}
		}
		return ans;
	}
	//拓展数据域,加上id
	template<typename T>
	static inline vector<pair<T, int>>expandWithId(const vector<T>& v)
	{
		vector<pair<T, int>>ans;
		ans.resize(v.size());
		for (int i = 0; i < v.size(); i++)ans[i].first = v[i], ans[i].second = i;
		return ans;
	}
	//给vector拓展,加上id并拓展成稳定排序
	template<typename T>
	static inline vector<pair<T, int>> sortWithId(const vector<T>& v)
	{
		vector<pair<T, int>>ans = expandWithId(v);
		sort(ans.begin(), ans.end(), cmpPair<T, int>);
		return ans;
	}
	//给vector拓展,加上id,但只按照原数据进行排序
	template<typename T>
	static inline vector<pair<T, int>> sortWithOrderMatch(const vector<T>& v)
	{
		vector<pair<T, int>>ans = expandWithId(v);
		sort(ans.begin(), ans.end(), cmpJustFirst<T, int>);
		return ans;
	}
	//排序后数组中的每个数的原ID,输入8 5 6 7,输出1 2 3 0,也可以直接求逆置换
	template<typename T>
	static inline vector<int> sortId(const vector<T>& v)
	{
		auto vp = sortWithId(v);
		vector<int>ans;
		transform(vp.begin(), vp.end(), back_inserter(ans), [](const pair<T, int>& p) {return p.second; });
		return ans;
	}
	//每个数在排序后的数组中的ID,输入8 5 6 7,输出3 0 1 2
	template<typename T>
	static inline vector<int> sortId2(const vector<T>& v)
	{
		return sortId(sortId(v));
	}
	//给v排序,v2按照同样的顺序调整,输入{1,3,2}{4,5,6},输出{1,2,3}{4,6,5}
	template<typename T, typename T2>
	static inline void sortExtend(vector<T>& v, vector<T2>& v2)
	{
		auto ids = sortId(v);
		auto v3 = v, v4 = v2;
		for (int i = 0; i < v.size(); i++)v[i] = v3[ids[i]], v2[i] = v4[ids[i]];
	}
	//2个vector中寻找和为s的对,返回结果的每一行都是[id1,id2]
	template<typename T>
	static vector<vector<int>> findSum(vector<T>v1, vector<T>v2, T s)
	{
		vector<vector<int>>ans;
		int m = min((long long)(v1.size() * v2.size()), (long long)12345678);
		ans.reserve(m);
		vector<int>tmp(2);
		vector<int>v3 = sortId(v2);
		sort(v2.begin(), v2.end(), cmp<T>);
		for (int i = 0; i < v1.size(); i++)
		{
			auto it1 = lower_bound(v2.begin(), v2.end(), s - v1[i]);
			auto it2 = upper_bound(v2.begin(), v2.end(), s - v1[i]);
			tmp[0] = i;
			for (auto j = it1; j < it2; j++)
			{
				tmp[1] = v3[j - v2.begin()];
				ans.push_back(tmp);
			}
		}
		return ans;
	}
	//vector的字典序比较,v1<v2是true,v1>=v2是false
	template<typename T>
	static bool cmpVector(const vector<T>& v1, const vector<T>& v2)
	{
		for (int i = 0; i < v1.size() && i < v2.size(); i++)
		{
			if (v1[i] != v2[i])return v1[i] < v2[i];
		}
		return v1.size() < v2.size();
	}
	//vector的字典序排序
	template<typename T>
	static void sortVector(vector<vector<T>>& v)
	{
		sort(v.begin(), v.end(), cmpVector<T>);
	}
private:
	template<typename T>
	static inline bool cmp(T a, T b)
	{
		return a < b;
	}
	static inline bool cmp(string a, string b)
	{
		return a.length() < b.length();
	}
	template<typename T, typename T2>
	static inline bool cmpPair(pair<T, T2> x, pair<T, T2> y)
	{
		if (cmp(x.first, y.first))return true;
		if (cmp(y.first, x.first))return false;
		return cmp(x.second, y.second);
	}
	template<typename T, typename T2>
	static inline bool cmpJustFirst(pair<T, T2> x, pair<T, T2> y)
	{
		return cmp(x.first, y.first);
	}
};

2,测试代码

template<typename T>
static bool IsSame(const T &a, const T &b)
{
	return a == b;
}
template<typename T>
static bool IsSame(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() - v2.size())return false;
	for (int i = 0; i < v1.size(); i++)if (!IsSame(v1[i], v2[i]))return false;
	return true;
}
template<typename T, typename T2>
static bool IsSame(const pair<T,T2>&p1, const pair<T, T2>&p2)
{
	return IsSame(p1.first, p2.first) && IsSame(p1.second, p2.second);
}

#define EXPECT_EQ(a,b) if(!IsSame(a,b)){cout<<"ERROR!!!!!!!!!\n";return false;}

bool testSortWithOrderMatch()
{
	vector<int> v{ 1,4,2,5,3 };
	auto ans = SortWithOrderMatch(v);
	vector<pair<int,int>> v2{ {1,0},{2,2}, {3,4}, {4,1},{5,3} };
	EXPECT_EQ(ans, v2);
	return true;
}
bool testVectorOpt()
{
	vector<int>v{ 1,4,4,1 };
	auto vp = Fshr(v, false);
	EXPECT_EQ(vp, (vector<pair<int, int>>{make_pair(1, 1), make_pair(4, 2), make_pair(1, 1)}));
	vp = Fshr(v, true);
	EXPECT_EQ(vp, (vector<pair<int, int>>{make_pair(1, 2), make_pair(4, 2)}));
	v = Funshr(vp);
	EXPECT_EQ(v, (vector<int>{ 1, 1, 4, 4}));
	vector<vector<int>> v2{ v,v };
	auto v3 = Fforeach(v2);
	EXPECT_EQ(v3.size(), v.size() * v.size());
	v = { 1,2,3 };
	map<int, vector<int>>options;
	options[1] = { 4 }, options[3] = { 5 };
	auto v4 = ChangeMeiJu(v, options);
	EXPECT_EQ(v4, (vector<vector<int>> { {1, 2, 3}, { 4,2,3 }, { 1,2,5 }, { 4,2,5 } }));
	map<int, vector<int>>options2;
	options2[1] = { 6 };
	options2[2] = { 7 };
	v4 = SubMeiJu(v, 3, options2);
	EXPECT_EQ(v4, (vector<vector<int>> { {1, 2, 3}, { 1,6,3 }, { 1,2,7 }, { 1,6,7 } }));
	v = vector<int>{ 8, 5, 6, 7 };
	EXPECT_EQ(SortId(v), (vector<int>{1, 2, 3, 0}));
	EXPECT_EQ(SortId2(v), (vector<int>{3, 0, 1, 2}));
	//给v排序,v2按照同样的顺序调整,输入,输出{1,2,3}{4,6,5}
	vector<int>v5{ 1,3,2 };
	vector<int>v6{ 4,5,6 };
	SortExtend(v5, v6);
	EXPECT_EQ(v5, (vector<int>{ 1, 2, 3 }));
	EXPECT_EQ(v6, (vector<int>{ 4, 6, 5 }));
	auto v7 = FindSum(v, v, 13);
	EXPECT_EQ(int(v7.size()), 4); //85 58 67 76
	EXPECT_EQ(CmpVector(v, vector<int>{ 8, 6, 5, 7 }), true);
	EXPECT_EQ(CmpVector(v, v), false);
	v2 = { {2,3},{1,2} };
	SortVector(v2);
	EXPECT_EQ(v2, (vector<vector<int>>{ {1, 2}, { 2,3 }}));
	return true;
}

int main()
{
	if (testSortWithOrderMatch() && testVectorOpt())cout << "test succ!";
	return 0;
}

五,vector的计算

1,代码

class VectorCal
{
public:
	//2个vector相加
	template<typename T>
	static vector<T> vecAdd(const vector<T>& v1, const vector<T>& v2)
	{
		vector<T>v(max(v1.size(), v2.size()));
		for (int i = 0; i < v.size(); i++)v[i] = 0;
		for (int i = 0; i < v1.size(); i++)v[i] += v1[i];
		for (int i = 0; i < v2.size(); i++)v[i] += v2[i];
		return v;
	}
	//枚举2个vector的两数之和
	template<typename T>
	static vector<T> everySum(vector<T>& v1, vector<T>& v2)
	{
		vector<T>ans;
		ans.resize(v1.size() * v2.size());
		int k = 0;
		for (int i = 0; i < v1.size(); i++)for (int j = 0; j < v2.size(); j++)ans[k++] = v1[i] + v2[j];
		return ans;
	}
	//判断2个vector(一维或二维)是否全等
	template<typename T>
	static bool vecIsSame(const vector<T>& v1, const vector<T>& v2)
	{
		if (v1.size() - v2.size())return false;
		for (int i = 0; i < v1.size(); i++)if (v1[i] != v2[i])return false;
		return true;
	}
	template<typename T>
	static bool vecIsSame(const vector<vector<T>>& v1, const vector<vector<T>>& v2) {
		if (v1.size() - v2.size())return false;
		for (int i = 0; i < v1.size(); i++)if (!vecIsSame(v1[i], v2[i]))return false;
		return true;
	}
	//二维数组去掉重复行
	template<typename T>
	static vector<vector<T>> deleteSameLine(const vector<vector<T>>& v)
	{
		vector<vector<T>>ans;
		ans.reserve(v.size());
		for (int i = 0; i < v.size(); i++)
		{
			bool flag = true;
			for (int j = i + 1; flag && j < v.size(); j++)if (vecIsSame(v[i], v[j]))flag = false;
			if (flag)ans.push_back(v[i]);
		}
		return ans;
	}
	//判断vector中是否含有重复元素
	template<typename T>
	static bool haveSameData(vector<T> v)// not const
	{
		sort(v.begin(), v.end());
		for (int i = 1; i < v.size(); i++)if (v[i] == v[i - 1])return true;
		return false;
	}
	//删除二维vector中,含有重复元素的行
	template<typename T>
	static vector<vector<T>> deleteLineWithSameDatas(vector<vector<T>>& v)
	{
		vector<vector<int>>ans;
		ans.reserve(v.size());
		for (int i = 0; i < v.size(); i++)
		{
			if (!haveSameData(v[i]))ans.push_back(v[i]);
		}
		return ans;
	}
	//2个vector的卷积
	template<typename T>
	static vector<T> vecConvolution(vector<T>& v1, vector<T>& v2)
	{
		vector<T>ans(v1.size() + v2.size() - 1);
		for (int i = 0; i < v1.size(); i++)for (int j = 0; j < v2.size(); j++)ans[i + j] += v1[i] * v2[j];
		return ans;
	}
};

2,测试代码


template<typename T>
static bool IsSame(const T &a, const T &b)
{
	return a == b;
}
template<typename T>
static bool IsSame(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() - v2.size())return false;
	for (int i = 0; i < v1.size(); i++)if (!IsSame(v1[i], v2[i]))return false;
	return true;
}
template<typename T, typename T2>
static bool IsSame(const pair<T,T2>&p1, const pair<T, T2>&p2)
{
	return IsSame(p1.first, p2.first) && IsSame(p1.second, p2.second);
}

#define EXPECT_EQ(a,b) if(!IsSame(a,b)){cout<<"ERROR!!!!!!!!!\n";return false;}


bool testDeleteLineWithSameDatas()
{
	vector<vector<int>>v1{ {1,2,3},{3,4,3},{4,5},{5,6} };
	vector<vector<int>>v2{ {1,2,3},{4,5},{5,6} };
	EXPECT_EQ(DeleteLineWithSameDatas(v1), v2);
	return true;
}
bool testVectorCal()
{
	vector<int>v1{ 8,5,6,7 }, v2{ 4,5,6,7 };
	EXPECT_EQ(VecAdd(v1, v2), (vector<int>{12, 10, 12, 14}));
	EXPECT_EQ(EverySum(v1, v2).size(), v1.size() * v2.size());
	vector<vector<int>>v3{ v1,v2,v1 };
	EXPECT_EQ(HaveSameData(v3), true);
	v3 = DeleteSameLine(v3);
	EXPECT_EQ(int(v3.size()), 2);
	EXPECT_EQ(HaveSameData(v3), false);
	EXPECT_EQ(VecIsSame(v1, v2), false);
	v2[0] = 8;
	EXPECT_EQ(VecIsSame(v1, v2), true);
	EXPECT_EQ(VecConvolution(v1, v2).size(), v1.size() + v2.size() - 1);
	return true;
}

int main()
{
	if (testDeleteLineWithSameDatas() && testVectorCal())cout << "test succ!";
	return 0;
}

六,单链表

1,代码

#ifdef LOCAL
struct listtNode {
	int val;
	listtNode* next;
	listtNode(int x) : val(x), next(NULL) {}
};
#define ListNode listtNode
#endif
class LinkList
{
public:
	//构建链表
	static ListNode* initLinkList(const vector<int>& v)
	{
		ListNode* head = new ListNode(0);
		ListNode* tail = head;
		for (auto vi : v)tail = tail->next = new ListNode(vi);
		return head->next;
	}
	//打印链表
	static void outLinkList(ListNode* head)
	{
		while (head) {
			cout << head->val << " ";
			head = head->next;
		}
	}
	//获取链表长度
	static int linkGetLength(ListNode* p)
	{
		int ans = 0;
		while (p)
		{
			ans++;
			p = p->next;
		}
		return ans;
	}
    //两个链表的数据是否全等
	static bool isSameLinkList(ListNode*p1, ListNode*p2)
	{
		if (!p1 && !p2)return true;
		return p1 && p2 && p1->val == p2->val && isSameLinkList(p1->next, p2->next);
	}
	//链表反转,返回新的head
	static ListNode* linkReverse(ListNode* p)
	{
		if (p == NULL)return p;
		ListNode* q1;
		ListNode* q2;
		q1 = p->next, p->next = NULL;
		while (q1)
		{
			q2 = q1->next, q1->next = p, p = q1, q1 = q2;
		}
		return p;
	}
	//链表中倒数第k个节点
	static ListNode* getKthFromEnd(ListNode* head, int k) {
		ListNode* p = head;
		while (p && k--)p = p->next;
		while (p)p = p->next, head = head->next;
		return head;
	}
	//链表最后一个节点
	static ListNode* getTail(ListNode* head)
	{
		return getKthFromEnd(head,1);
	}
	//留下前k个节点,把后面的切下来并返回
	static ListNode* linkSplit(ListNode* head, int k)
	{
		while (--k && head) {
			head = head->next;
		}
		if (!head)return head;
		auto ans = head->next;
		head->next = nullptr;
		return ans;
	}
	//直接合并2个链表
	static void linkMerge(ListNode* p1, ListNode* p2)
	{
		getTail(p1)->next = p2;
	}
	//把两个链表交叉合并为一个链表
	static ListNode* mergeTwoLists(ListNode* p, ListNode* q) {
		if (!p)return q;
		if (!q)return p;
		ListNode* pnext, * qnext, * ans = p;
		while (p && q)
		{
			if (p->next == NULL && q->next != NULL)
			{
				p->next = q;
				break;
			}
			pnext = p->next, qnext = q->next;
			p->next = q, q->next = pnext;
			p = pnext, q = qnext;
		}
		return ans;
	}
	//把两个升序的链表合并为一个升序的链表
	static ListNode* mergeTwoUpLists(ListNode* p, ListNode* q) {
		if (!p)return q;
		if (!q)return p;
		ListNode* head;
		if (p->val < q->val)head = p, p = p->next;
		else head = q, q = q->next;
		ListNode* ans = head;
		while (p && q)
		{
			if (p->val < q->val)ans->next = p, ans = p, p = p->next;
			else ans->next = q, ans = q, q = q->next;
		}
		if (p)ans->next = p;
		else ans->next = q;
		return head;
	}
	//把链表转化成结构体指针数组
	static vector<ListNode*> listToVec(ListNode* head)
	{
		vector<ListNode*>ans;
		while (head)
		{
			ans.push_back(head);
			head = head->next;
		}
		return ans;
	}
	//把结构体指针数组转化成链表
	static ListNode* vecToList(vector<ListNode*>v)
	{
		if (v.empty())return NULL;
		for (int i = 0; i < v.size() - 1; i++)v[i]->next = v[i + 1];
		v[v.size() - 1]->next = NULL;
		return v[0];
	}
	//链表排序
	static ListNode* sortLinkList(ListNode* head)
	{
		vector<ListNode*>v = listToVec(head);
		sort(v.begin(), v.end(), cmp);
		return vecToList(v);
	}
	//判断链表是否有环,有环返回环中任意节点,没环返回NULL
	static ListNode* getAnyoneInCycle(ListNode* head) {
		if (!head)return NULL;
		ListNode* p1 = head, * p2 = head->next;
		while (p1 != p2)
		{
			if (!p1)return NULL;
			p1 = p1->next;
			if (!p2)return NULL;
			p2 = p2->next;
			if (!p2)return NULL;
			p2 = p2->next;
		}
		return p1;
	}
	//求链表环的长度,没环返回0
	static int getCycleLen(ListNode* head) {
		ListNode* p = getAnyoneInCycle(head);
		if (!p)return 0;
		ListNode* q = p->next;
		int ans = 1;
		while (q != p)q = q->next, ans++;
		return ans;
	}
	//求链表环的第一个节点,没环返回NULL
	static ListNode* getFirstInCycle(ListNode* head) {
		int len = getCycleLen(head);
		if (len == 0)return NULL;
		ListNode* p = head;
		while (len--)p = p->next;
		while (head != p)head = head->next, p = p->next;
		return p;
	}
private:
	static bool cmp(ListNode*& a, ListNode*& b)
	{
		return a->val < b->val;
	}
};

2,测试代码


template<typename T>
static bool IsSame(const T &a, const T &b)
{
	return a == b;
}
template<typename T>
static bool IsSame(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() - v2.size())return false;
	for (int i = 0; i < v1.size(); i++)if (!IsSame(v1[i], v2[i]))return false;
	return true;
}
template<typename T, typename T2>
static bool IsSame(const pair<T,T2>&p1, const pair<T, T2>&p2)
{
	return IsSame(p1.first, p2.first) && IsSame(p1.second, p2.second);
}

#define EXPECT_EQ(a,b) if(!IsSame(a,b)){cout<<"ERROR!!!!!!!!!\n";return false;}
#define EXPECT_LINK_EQ(a,b) if(!IsSameLinkList((a),(b))){cout<<"ERROR!!!!!!!!!\n";return false;}

bool testLinkList()
{
	vector<int>v{ 1,2,3,4 }, v2{ 4,3,2,1 };
	auto p = InitLinkList(v);
	//OutLinkList(p);
	EXPECT_EQ(LinkGetLength(p), int(v.size()));
	auto p2 = LinkReverse(InitLinkList(v2));
	EXPECT_LINK_EQ(p, p2);
	auto p3 = GetKthFromEnd(p, 3);
	EXPECT_EQ(p3->val, 2);
	EXPECT_EQ(GetTail(p)->val, 4);
	EXPECT_EQ(LinkGetLength(p), 4);
	p3 = LinkSplit(p, 3); //留下前k个节点,把后面的切下来并返回
	EXPECT_EQ(LinkGetLength(p), 3);
	EXPECT_EQ(LinkGetLength(p3), 1);
	LinkMerge(p, p3);
	EXPECT_LINK_EQ(p, p2);
	p2->val = 5;
	EXPECT_LINK_EQ(MergeTwoLists(p, p2), InitLinkList(vector<int>{1, 5, 2, 2, 3, 3, 4, 4}));
	p = InitLinkList(vector<int>{ 1, 2, 3, 4 });
	p2 = InitLinkList(vector<int>{ 0, 2, 3, 4 });
	EXPECT_LINK_EQ(MergeTwoUpLists(p, p2), InitLinkList(vector<int>{0, 1, 2, 2, 3, 3, 4, 4}));
	return true;
}
bool testLinkList2()
{
	vector<int>v{ 1,2,3,4 };
	auto p = InitLinkList(v);
	auto p2 = VecToList(ListToVec(p));
	EXPECT_LINK_EQ(p, p2);
	vector<int>v2{ 3,4,1,2 };
	p2 = SortLinkList(InitLinkList(v2));
	EXPECT_LINK_EQ(p, p2);
	p->next->next->next->next = p->next;//1 2 3 4 2
	EXPECT_EQ(GetAnyoneInCycle(p)->val >= 2, true);
	EXPECT_EQ(GetCycleLen(p), 3);
	EXPECT_EQ(GetFirstInCycle(p)->val, 2);
	return true;
}

int main()
{
	if (testLinkList() && testLinkList2())cout << "test succ!";
	return 0;
}

七,双向循环链表

1,代码

struct DeListNode {
	int val;
	DeListNode* left;
	DeListNode* right;
	DeListNode() {}
	DeListNode(int _val) {
		val = _val;
		left = NULL;
		right = NULL;
	}
	DeListNode(int _val, DeListNode* _left, DeListNode* _right) {
		val = _val;
		left = _left;
		right = _right;
	}
};
class DeLinkList
{
public:
	//创建单节点双向循环链表
	static DeListNode* getSingleDeList(int val = 0)
	{
		DeListNode* p = new DeListNode();
		p->left = p, p->right = p, p->val = val;
		return p;
	}
	//合并双向循环链表
	static void mergeDelist(DeListNode* p1, DeListNode* p2)
	{
		if (!p1 || !p2)return;
		p1->left->right = p2, p2->left->right = p1;
		DeListNode* tmp = p2->left;
		p2->left = p1->left;
		p1->left = tmp;
	}
	//获取链表长度
	static int getLengthOfDeLL(DeListNode* p)
	{
		int ans = 1;
		auto head = p;
		p = p->right;
		while (p != head)
		{
			ans++;
			p = p->right;
		}
		return ans;
	}
};

2,测试代码


template<typename T>
static bool IsSame(const T &a, const T &b)
{
	return a == b;
}
template<typename T>
static bool IsSame(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() - v2.size())return false;
	for (int i = 0; i < v1.size(); i++)if (!IsSame(v1[i], v2[i]))return false;
	return true;
}
template<typename T, typename T2>
static bool IsSame(const pair<T,T2>&p1, const pair<T, T2>&p2)
{
	return IsSame(p1.first, p2.first) && IsSame(p1.second, p2.second);
}

#define EXPECT_EQ(a,b) if(!IsSame(a,b)){cout<<"ERROR!!!!!!!!!\n";return false;}

bool testDeLinkList()
{
	auto p = GetSingleDeList(1);
	auto p2 = GetSingleDeList(2);
	EXPECT_EQ(GetLengthOfDeLL(p), 1);
	MergeDelist(p, p2);
	EXPECT_EQ(GetLengthOfDeLL(p), 2);
	return true;
}

int main()
{
	if (testDeLinkList())cout << "test succ!";
	return 0;
}

八,STL操作封装、拓展数据结构

1,代码

class StlBasicOpt
{
public:
	//获取列表某处的值
	template<typename T>
	static T vecGet(const vector<T>& v, int id)
	{
		return (id >= 0 && id < v.size()) ? v[id] : T{};
	}
	//id处覆盖或者添加一个数
	template<typename T>
	static void finsert(vector<T>& v, int id, T x)
	{
		if (id<0 || id>v.size())return;
		if (id == v.size())v.push_back(x);
		v[id] = x;
	}
	//multi***容器x删除一个数值n
	template<typename T, typename T2>
	static void delOnlyOne(T& x, T2 n)
	{
		auto it = x.find(n);
		if (it != x.end())x.erase(it);
	}
	//删除最后一个元素
	template<typename T>
	static void delEnd(T& x)
	{
		x.erase(--(x.end()));
	}
};

//栈的拓展,支持获取最值,所有接口时间复杂度都是 O(1)
class MinMaxStack {
public:
	MinMaxStack(int type) { //0最小栈 1最大栈
		this->type = type;
	}
	void push(int x) {//入栈
		s.push(x);
		if (m.empty() || (type ? (m.top() <= x) : (m.top() >= x)))m.push(x);
	}
	void pop() {//出栈
		if (m.top() == s.top())m.pop();
		s.pop();
	}
	int top() {//获取栈顶
		return s.top();
	}
	int minMax() {//获取最值
		return m.top();
	}
private:
	stack<int>s;//主栈
	stack<int>m;//单调栈
	int type;
};
//栈的拓展,支持删除最值,所有接口时间复杂度都在 O(log n)之内
class MinMaxStack2 : public StlBasicOpt
{
public:
	MinMaxStack2(int type) {//0最小栈 1最大栈
		this->type = type;
	}
	int peekMinMax() { //获取最值
		while (m.rbegin()->second.empty())delEnd(m);
		return m.rbegin()->first;
	}
	int popMinMax() { //获取最值并删除
		int t = peekMinMax();
		m2[t].insert(*(m[t].rbegin()));
		delEnd(m[t]);
		return t;
	}
	void push(int t) {
		v.push_back(t);
		int num = 0;
		if (!m[t].empty())num = max(num, *(m[t].rbegin()));
		if (!m2[t].empty())num = max(num, *(m2[t].rbegin()));
		m[t].insert(num + 1);
	}
	int pop() {
		int t = top();
		delEnd(m[t]);
		delEnd(v);
		return t;
	}
	int top() {
		while (true) {
			int t = v.back();
			if (m2[t].empty())break;
			if (!m[t].empty()) {
				if (type ? (*(m[t].rbegin()) > *(m2[t].rbegin())) : (*(m[t].rbegin()) < *(m2[t].rbegin())))break;
			}
			delEnd(m2[t]);
			delEnd(v);
		}
		return v.back();
	}
private:
	map<int, set<int>>m;//现存列表
	map<int, set<int>>m2;//删除列表
	vector<int>v;
	int type;
};

//队列的拓展,支持获取最值,所有接口的均摊时间复杂度都是O(1)
class MinMaxQueue : public StlBasicOpt
{
public:
	MinMaxQueue(int type) { //0最小队列 1最大队列
		this->type = type, vlen = 0;
	}
	int max_value() {
		if (q.empty())return error;
		return v[0];
	}
	void push_back(int value) {
		q.push(value);
		bool flag = true;
		for (int i = vlen; flag && i > 0; i--)
		{
			if (type ? (value <= v[i - 1]) : (value >= v[i - 1]))
			{
				finsert(v, i, value);
				vlen = i + 1;
				flag = false;
			}
		}
		if (flag)
		{
			finsert(v, 0, value);
			vlen = 1;
		}
	}
	int pop_front() {
		if (q.empty())return error;
		int ans = q.front();
		q.pop();
		if (v[0] == ans)
		{
			v.erase(v.begin());
			vlen--;
		}
		return ans;
	}
private:
	queue<int>q;
	vector<int>v;
	int type;
	int vlen;
	int error = -1;
};
template<typename T>
class QueueWithNoSameData //不含重复元素的队列
{
public:
	void push(T x) {
		if (m[x] == 0)q.push(x), m[x] = 1;
	}
	void pop() {
		m[q.front()] = 0;
		q.pop();
	}
	T front() {
		return q.front();
	}
	bool empty() {
		return q.empty();
	}
private:
	queue<T>q;
	map<T, int>m;
};

2,测试代码


template<typename T>
static bool IsSame(const T &a, const T &b)
{
	return a == b;
}
template<typename T>
static bool IsSame(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() - v2.size())return false;
	for (int i = 0; i < v1.size(); i++)if (!IsSame(v1[i], v2[i]))return false;
	return true;
}
template<typename T, typename T2>
static bool IsSame(const pair<T,T2>&p1, const pair<T, T2>&p2)
{
	return IsSame(p1.first, p2.first) && IsSame(p1.second, p2.second);
}

#define EXPECT_EQ(a,b) if(!IsSame(a,b)){cout<<"ERROR!!!!!!!!!\n";return false;}

bool testStlBasicOpt()
{
	vector<int>v{ 1, 2, 4, 6 };
	EXPECT_EQ(VecGet(v, 3), 6);
	EXPECT_EQ(VecGet(v, 4), 0);
	Finsert(v, 2, 7);
	EXPECT_EQ(v, (vector<int>{1, 2, 7, 6}));
	Finsert(v, 4, 7);
	EXPECT_EQ(v, (vector<int>{1, 2, 7, 6, 7}));
	multiset<int>s{ 1, 2, 3, 2, 4 };
	EXPECT_EQ(int(s.size()), 5);
	DelOnlyOne(s, 2);
	DelEnd(s);
	EXPECT_EQ(int(s.size()), 3);
	return true;
}

bool testMinStack()
{
	MinMaxStack s(0);
	s.push(3);
	s.push(1);
	s.push(2);
	EXPECT_EQ(s.top(), 2);
	EXPECT_EQ(s.minMax(), 1);
	s.pop();
	EXPECT_EQ(s.top(), 1);
	return true;
}
bool testMaxStack()
{
	MinMaxStack2 s(1);
	s.push(1);
	s.push(3);
	s.push(2);
	EXPECT_EQ(s.top(), 2);
	EXPECT_EQ(s.peekMinMax(), 3);
	EXPECT_EQ(s.popMinMax(), 3);
	EXPECT_EQ(s.popMinMax(), 2);
	return true;
}
bool testMaxQueue()
{
	MinMaxQueue q(1);
	q.push_back(1);
	q.push_back(2);
	q.push_back(1);
	q.push_back(2);
	q.pop_front();
	EXPECT_EQ(q.max_value(), 2);
	return true;
}
bool testQueueWithNoSameData()
{
	QueueWithNoSameData<int>q;
	q.push(1);
	q.push(2);
	q.push(1);
	EXPECT_EQ(q.front(), 1);
	q.pop();
	EXPECT_EQ(q.front(), 2);
	q.pop();
	EXPECT_EQ(q.empty(), true);
}
int main()
{
	if (testStlBasicOpt() && testMinStack() && testMaxStack() && testMaxQueue() && testQueueWithNoSameData())cout << "test succ!";
	return 0;
}

九,单调栈、单调队列、背包

1,代码


//单调栈
class MonotonicStack {
public:
	MonotonicStack(int type, bool force) { //0递减栈,栈顶最小,1递增栈,栈顶最大, force表示是否是强制单调栈
		this->type = type, this->force = force;
	}
	void push(int x) {
		if (force) {
			while (!s.empty() && (type ? (s.top() > x) : (s.top() < x)))s.pop();
			s.push(x);
		}
		else {
			if (s.empty() || (type ? (s.top() <= x) : (s.top() >= x)))s.push(x);
		}
	}
	void pop() {
		if (!s.empty())s.pop();
	}
	int top() {
		return s.top();
	}
	int size() {
		return s.size();
	}
private:
	stack<int>s;
	int type;
	bool force;
};
//单调队列
class MonotonicQueue {
public:
	MonotonicQueue(int type) { //0递增队列,队首最小,1递减队列,队首最大
		this->type = type;
		id = 0;
	}
	void push_back(int x) {
		while (!q.empty() && (type ? (m[q.back()] < x) : (m[q.back()] > x)))q.pop_back();
		q.push_back(id);
		m[id++] = x;
	}
	void pop_front() {
		if (!q.empty())q.pop_front();
	}
	void pop_back() {
		if (!q.empty())q.pop_back();
	}
	int frontId() {
		return q.front();
	}
	int front() {
		return m[q.front()];
	}
	int tailId() {
		return q.back();
	}
	int size() {
		return q.size();
	}
private:
	deque<int>q;
	map<int, int>m;
	int type, id;
};
//01背包、完全背包、多重背包、混合背包
class Pack {
public:
	//01背包,输入总体积,每个物品的体积和得分,输出最高总得分
	static int pack01(int v, const vector<int>& volume, const vector<int>& score) {
		vector<int>ans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++)pack01Opt(v, volume[i], score[i], ans);
		return ans[v];
	}
	//0-1增强代价背包,需要有volumePlus大小的空间,才能放入volume大小的物品,输出最高总得分
	static int packPlus(int v, const vector<int>& volumePlus, const vector<int>& volume, const vector<int>& score) {
		vector<node>vec = transPackPlusToNodes(volumePlus, volume, score);
		vector<int>ans(v + 1, 0);
		for (int i = 0; i < vec.size(); i++) {
			for (int j = v; j >= vec[i].vp; j--) {
				ans[j] = max(ans[j], ans[j - vec[i].v] + vec[i].s);
			}
		}
		return ans[v];
	}
	//0-1双得分背包,每个物品有2个得分,输出score的最高总得分,以及在该得分前提下,score2的最高总得分,score2可以为负
	static vector<int> packDoubleScore(int v, const vector<int>& volume, const vector<int>& score, const vector<int>& score2) {
		vector<int>ans(v + 1, 0), ans2(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			for (int j = v; j >= volume[i]; j--) {
				int j2 = j - volume[i];
				if (ans[j] < ans[j2] + score[i])ans[j] = ans[j2] + score[i], ans2[j] = ans2[j2] + score2[i];
				else if (ans[j] == ans[j2] + score[i] && ans2[j] < ans2[j2] + score2[i])ans2[j] = ans2[j2] + score2[i];
			}
		}
		return vector<int>{ans[v], ans2[v]};
	}
	//01背包组合计数,输入总体积,每个物品的体积,输出刚好塞满的方案数,不区分顺序
	static int pack01Num(int v, const vector<int>& volume) {
		vector<int>ans(v + 1, 0);
		ans[0] = 1;
		for (int i = 0; i < volume.size(); i++) {
			for (int j = v; j >= volume[i]; j--) {
				ans[j] += ans[j - volume[i]];
			}
		}
		return ans[v];
	}
	//完全背包,输入总体积,每个物品的体积和得分,输出最高总得分
	static int packComplete(int v, const vector<int>& volume, const vector<int>& score) {
		vector<int>ans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++)pack01Opt(v, volume[i], score[i], ans);
		return ans[v];
	}
	//完全增强代价背包,需要有volumePlus大小的空间,才能放入volume大小的物品,输出最高总得分
	static int packCompletePlus(int v, const vector<int>& volumePlus, const vector<int>& volume, const vector<int>& score) {
		vector<node>vec = transPackPlusToNodes(volumePlus, volume, score);
		vector<int>ans(v + 1, 0);
		for (int i = 0; i < vec.size(); i++) {
			for (int j = vec[i].vp; j <= v; j++) {
				ans[j] = max(ans[j], ans[j - vec[i].v] + vec[i].s);
			}
		}
		return ans[v];
	}
	//完全双得分背包,每个物品有2个得分,输出score的最高总得分,以及在该得分前提下,score2的最高总得分,score2可以为负
	static vector<int> packCompleteDoubleScore(int v, const vector<int>& volume, const vector<int>& score, const vector<int>& score2) {
		vector<int>ans(v + 1, 0), ans2(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			for (int j = volume[i]; j <= v; j++) {
				int j2 = j - volume[i];
				if (ans[j] < ans[j2] + score[i])ans[j] = ans[j2] + score[i], ans2[j] = ans2[j2] + score2[i];
				else if (ans[j] == ans[j2] + score[i] && ans2[j] < ans2[j2] + score2[i])ans2[j] = ans2[j2] + score2[i];
			}
		}
		return vector<int>{ans[v], ans2[v]};
	}
	//完全背包组合计数,输入总体积,每个物品的体积,输出刚好塞满的方案数,不区分顺序
	static int packCompleteNum(int v, const vector<int>& volume) {
		vector<int>ans(v + 1, 0);
		ans[0] = 1;
		for (int i = 0; i < volume.size(); i++) {
			for (int j = volume[i]; j <= v; j++) {
				ans[j] += ans[j - volume[i]];
			}
		}
		return ans[v];
	}
	//完全背包排列计数,输入总体积,每个物品的体积,输出刚好塞满的方案数,区分顺序
	static long long packCompleteNumA(int v, const vector<int>& volume, long long p = UINT_MAX) {
		vector<long long>ans(v + 1, 0);
		ans[0] = 1;
		for (int j = 0; j <= v; j++) {
			for (int i = 0; i < volume.size(); i++) {
				if (j >= volume[i])ans[j] = (ans[j] + ans[j - volume[i]]) % p;
			}
		}
		return ans[v];
	}
	//多重背包,输入总体积,每个物品的体积和数量和得分,输出最高总得分
	static int packMulti(int v, const vector<int>& volume, const vector<int>& num, const vector<int>& score) {
		vector<int>ans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++)packMultiOpt(v, volume[i], num[i], score[i], ans);
		return ans[v];
	}
	//01、完全、多重的混合背包,num=1是01背包,num=-1是完全背包,num>1是多重背包
	static int packMix(int v, const vector<int>& volume, const vector<int>& num, const vector<int>& score) {
		vector<int>ans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			if (num[i] == 1)pack01Opt(v, volume[i], score[i], ans);
			if (num[i] == -1)packCompleteOpt(v, volume[i], score[i], ans);
			if (num[i] > 1)packMultiOpt(v, volume[i], num[i], score[i], ans);
		}
		return ans[v];
	}
private:
	struct node
	{
		int vp, v, s;
		static bool cmp(node a, node b)
		{
			return a.vp - a.v < b.vp - b.v;
		}
	};
	static vector<node> transPackPlusToNodes(const vector<int>& volumePlus, const vector<int>& volume, const vector<int>& score)
	{
		vector<node>vec;
		for (int i = 0; i < volumePlus.size(); i++) {
			vec.push_back({ volumePlus[i],volume[i],score[i] });
		}
		sort(vec.begin(), vec.end(), node::cmp);
		return vec;
	}
	static inline void pack01Opt(int v, int volumei, int scorei, vector<int>& ans) {
		for (int j = v; j >= volumei; j--) {
			ans[j] = max(ans[j], ans[j - volumei] + scorei);
		}
	}
	static inline void packCompleteOpt(int v, int volumei, int scorei, vector<int>& ans) {
		for (int j = volumei; j <= v; j++) {
			ans[j] = max(ans[j], ans[j - volumei] + scorei);
		}
	}
	static inline void packMultiOpt(int v, int volumei, int numi, int scorei, vector<int>& ans) {
		for (int j = 0; j < volumei; j++) {
			MonotonicQueue q(1);
			for (int k = j; k <= v; k += volumei) {
				q.push_back(ans[k] - k / volumei * scorei);
				ans[k] = k / volumei * scorei + q.front();
				if (q.tailId() - numi == q.frontId())q.pop_front();
			}
		}
	}
};
//双代价背包
class PackDoubleVolume {
public:
	//0-1双代价背包,每个物品有2个代价,输出最高总得分
	static int pack01(int v, int v2, const vector<int>& volume, const vector<int>& volume2, const vector<int>& score) {
		vector<vector<int>>ans(v + 1, vector<int>(v2 + 1, 0));
		for (int i = 0; i < volume.size(); i++)pack01Opt(v, v2, volume[i], volume2[i], score[i], ans);
		return ans[v][v2];
	}
	//完全双代价背包,每个物品有2个代价,输出最高总得分
	static int packComplete(int v, int v2, const vector<int>& volume, const vector<int>& volume2, const vector<int>& score) {
		vector<vector<int>>ans(v + 1, vector<int>(v2 + 1, 0));
		for (int i = 0; i < volume.size(); i++)packCompleteOpt(v, v2, volume[i], volume2[i], score[i], ans);
		return ans[v][v2];
	}
	//多重双代价背包,每个物品有2个代价,输出最高总得分
	static int packMulti(int v, int v2, const vector<int>& volume, const vector<int>& volume2, const vector<int>& num, const vector<int>& score) {
		vector<vector<int>>ans(v + 1, vector<int>(v2 + 1, 0));
		for (int i = 0; i < volume.size(); i++) packMultiOpt(v, v2, volume[i], volume2[i], num[i], score[i], ans);
		return ans[v][v2];
	}
	//01、完全、多重的混合双代价背包,num=1是01背包,num=-1是完全背包,num>1是多重背包
	static int packMix(int v, int v2, const vector<int>& volume, const vector<int>& volume2, const vector<int>& num, const vector<int>& score) {
		vector<vector<int>>ans(v + 1, vector<int>(v2 + 1, 0));
		for (int i = 0; i < volume.size(); i++) {
			if (num[i] == 1)pack01Opt(v, v2, volume[i], volume2[i], score[i], ans);
			if (num[i] == -1)packCompleteOpt(v, v2, volume[i], volume2[i], score[i], ans);
			if (num[i] > 1)packMultiOpt(v, v2, volume[i], volume2[i], num[i], score[i], ans);
		}
		return ans[v][v2];
	}
private:
	static inline void pack01Opt(int v, int v2, int volumei, int volume2i, int scorei, vector<vector<int>>& ans) {
		for (int j = v; j >= volumei; j--) {
			for (int j2 = v2; j2 >= volume2i; j2--) {
				ans[j][j2] = max(ans[j][j2], ans[j - volumei][j2 - volume2i] + scorei);
			}
		}
	}
	static inline void packCompleteOpt(int v, int v2, int volumei, int volume2i, int scorei, vector<vector<int>>& ans) {
		for (int j = volumei; j <= v; j++) {
			for (int j2 = volume2i; j2 <= v2; j2++) {
				ans[j][j2] = max(ans[j][j2], ans[j - volumei][j2 - volume2i] + scorei);
			}
		}
	}
	static inline void packMultiOpt(int v, int v2, int volumei, int volume2i, int numi, int scorei, vector<vector<int>>& ans) {
		for (int j = 0; j <= v; j++) {
			for (int j2 = 0; j2 <= (j < volumei ? v2 : volume2i - 1); j2++) {
				MonotonicQueue q(1);
				for (int k = j, k2 = j2; k <= v, k2 <= v2; k += volumei, k2 += volume2i) {
					q.push_back(ans[k][k2] - k / volumei * scorei);
					ans[k][k2] = k / volumei * scorei + q.front();
					if (k / volumei - numi == q.frontId())q.pop_front();
				}
			}
		}
	}
};
//分组背包
class PackGroup {
public:
	//分组背包,输入总体积,每组每个物品的体积和得分,输出最高总得分
	static int packGroup01(int v, const vector<vector<int>>& volume, const vector<vector<int>>& score) {
		return packGroup01Ans(v, volume, score)[v];
	}
	//分组背包组合计数,输入总体积,每组每个物品的体积,输出刚好塞满的方案数,不区分顺序
	static int packGroup01Num(int v, const vector<vector<int>>& volume) {
		vector<int>ans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			for (int j = v; j >= 0; j--) {
				for (int k = 0; k < volume[i].size(); k++) {
					if (j >= volume[i][k])ans[j] += ans[j - volume[i][k]];
				}
			}
		}
		return ans[v];
	}
protected:
	//分组背包,输入总体积,每组每个物品的体积和得分,输出最高总得分
	static vector<int> packGroup01Ans(int v, const vector<vector<int>>& volume, const vector<vector<int>>& score) {
		vector<int>ans(v + 1, 0);
		for (int i = 0; i < volume.size(); i++) {
			for (int j = v; j >= 0; j--) {
				for (int k = 0; k < volume[i].size(); k++) {
					if (j >= volume[i][k])ans[j] = max(ans[j], ans[j - volume[i][k]] + score[i][k]);
				}
			}
		}
		return ans;
	}
};
//泛化物品背包
class PackGeneralize :public PackGroup {
public:
	//每个物品i都有一个价值函数score[i],拿j个i需要的代价是j,获得的价值是score[i][j]
	static int packComplete(int v, const vector<vector<int>>& score) {
		return packCompleteAns(v, score)[v];
	}
protected:
	static vector<int> packCompleteAns(int v, const vector<vector<int>>& score) {
		vector<vector<int>> volume2, score2;
		for (auto& s : score) {
			vector<int>vi, si;
			for (int i = 1; i <= v && i<s.size(); i++) {
				vi.push_back(i), si.push_back(s[i]);
			}
			volume2.push_back(vi), score2.push_back(si);
		}
		return packGroup01Ans(v, volume2, score2);
	}
};
//依赖背包(仅限森林)
class PackDepend :public PackGeneralize {
public:
	//依赖背包(仅限森林),children是每个节点的子节点集,所有节点编号0到n-1,children和volume和score的长度都为n
	static int packDependTrees(int v, const vector<vector<int>>& children, const vector<int>& volume, const vector<int>& score) {
		return packDependTrees(v, getRoots(children), children, volume, score)[v];
	}
	//依赖背包(仅限森林),fas是所有根节点,children是每个节点的子节点集,所有节点编号0到n-1,children和volume和score的长度都为n
	static vector<int> packDependTrees(int v, const vector<int>& roots, const vector<vector<int>>& children, const vector<int>& volume, const vector<int>& score) {
		vector<vector<int>> score2;
		for (auto root : roots) {
			score2.push_back(packDependTree(v, root, children, volume, score));
		}
		return PackGeneralize::packCompleteAns(v, score2);
	}
private:
	static vector<int> getRoots(const vector<vector<int>>& children) {
		map<int, int>m;
		for (auto& cs : children)for (auto x : cs)m[x]++;
		vector<int>roots;
		for (int i = 0; i < children.size(); i++)if (m[i] == 0)roots.push_back(i);
		return roots;
	}
	static vector<int> packDependTree(int v, int root, const vector<vector<int>>& children, const vector<int>& volume, const vector<int>& score) {
		vector<int> ans(v + 1, 0);
		if (volume[root] > v)return ans;
		if (children[root].empty()) {
			ans[volume[root]] = score[root];
			return ans;
		}
		return packDependTrees(v - volume[root], children[root], children, volume, score);
	}
};

2,测试代码


template<typename T>
static bool IsSame(const T &a, const T &b)
{
	return a == b;
}
template<typename T>
static bool IsSame(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() - v2.size())return false;
	for (int i = 0; i < v1.size(); i++)if (!IsSame(v1[i], v2[i]))return false;
	return true;
}
template<typename T, typename T2>
static bool IsSame(const pair<T,T2>&p1, const pair<T, T2>&p2)
{
	return IsSame(p1.first, p2.first) && IsSame(p1.second, p2.second);
}

#define EXPECT_EQ(a,b) if(!IsSame(a,b)){cout<<"ERROR!!!!!!!!!\n";return false;}

bool testMonotonicStack()
{
	MonotonicStack s(0, true);
	s.push(3); // 3
	s.push(2); // 3 2
	EXPECT_EQ(s.top(), 2);
	EXPECT_EQ(s.size(), 2);
	s.push(4); //先弹出2 再弹出3 再入栈4
	EXPECT_EQ(s.top(), 4);
	EXPECT_EQ(s.size(), 1);
	return true;
}

bool testMonotonicQueue()
{
	MonotonicQueue q(0);
	q.push_back(2);
	q.push_back(1);
	q.push_back(3);
	EXPECT_EQ(q.front(), 1);
	return true;
}


bool testPack() 
{
	vector<int>volume{ 2,4,5,8 };
	vector<int>score{ 3,10,10,18 };
	//01背包
	EXPECT_EQ(Pack::pack01(9, volume, score), 20);//10+10=20
	vector<int>volumePlus{ 3,6,6,8 };
	//0-1增强代价背包
	EXPECT_EQ(Pack::packPlus(9, volumePlus, volume, score), 18);//18=18
	vector<int>score2{ 0,-1,-2,3 };
	//0-1双得分背包
	EXPECT_EQ(Pack::packDoubleScore(13, volume, score, score2), (vector<int>{28, 2}));//10+18=28,-1+3=2
	//01背包组合计数
	EXPECT_EQ(Pack::pack01Num(10, vector<int>{2, 2, 3, 3, 5, 6}), 6); //2233 235 235 235 235 226 六种情况
	// 以下 待完善
	//完全背包
	//完全增强代价背包
	//完全双得分背包
	//完全背包组合计数
	//完全背包排列计数
	//多重背包
	//01、完全、多重的混合背包

	return true;
}
bool testPack2()
{
	// 以下 待完善
	//0-1双代价背包
	//完全双代价背包
	//多重双代价背包
	//01、完全、多重的混合双代价背包
	//分组背包
	//分组背包组合计数
	//泛化物品背包
	//依赖背包 * 2
	return true;
}

int main()
{
	if (testMonotonicStack() && testMonotonicQueue() && testPack() && testPack2())cout << "test succ!";
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值