【数据结构】二叉树题目代码总结 (快速排序与汉诺塔的非递归 、判断完全二叉树 、二叉链表交换左右孩子 、01背包问题)

1. 非递归:快速排序 汉诺塔

非递归思想启发博文:https://blog.csdn.net/bobbypollo/article/details/79891556
快速排序的学习博文:https://blog.csdn.net/qq_36528114/article/details/78667034

1的重点为二者的非递归,代码中的递归主要是在理解二者非递归思想时用于对比

递归的重要的一点就是必须先解决子问题,再基于子问题来解决当前问题。
即先进后出,
故递归转非递归时用来解决。

1.1 快速排序非递归
//快速排序递归非递归对比
#include <iostream>
#include <stack>
using namespace std;

//快速排序
template <class T>
int Particition(T* pa, int low, int high)
{
	int i = low, j = high;
	T temp = pa[i];
	while (i != j)
	{
		while (i<j && pa[j]>temp)
			j--;
		if (i < j)
			pa[i++] = pa[j];
		while (i < j && pa[i] < temp)
			i++;
		if (i < j)
			pa[j--] = pa[i];
	}
	pa[i] = temp;
	return i;
}
//快速排序递归算法
void QuickSoret(T* pa, int low, int high)
{
	if (low > high)
		return;
	int m = Particition(pa, low, high);
	QuickSoret(pa, low, m - 1);
	QuickSoret(pa, m + 1, high);
}
//快速排序非递归算法
template <class T>
void QuickSoret2(T* pa, int low, int high)
{
	T i,j;
	stack<T> S;
	if (low > high)
		return;
	int m;
	S.push(low);
	S.push(high);
	while (!S.empty())
	{
		j = S.top();
		S.pop();
		i = S.top();
		S.pop();
		m = Particition(pa, i, j);
		if (m - 1 > i)
		{
			S.push(i);
			S.push(m-1);
		}
		if (m + 1 < j)
		{
			S.push(m+1);
			S.push(j);
		}
	}
}
//附加验证
template<class T>
void PrintQuickSoretResout(T* pa, int low, int high)
{
	QuickSoret2(pa, low, high);
	for (int k = low; k <= high; k++)
		cout << pa[k] << "  ";
	cout << endl;
}
int main()
{
	int paa[10] = { 2,3,6,1,4,5,9,8,7,10 };
	PrintQuickSoretResout(paa, 0, 9);
}
1.2 汉诺塔非递归

这里写的汉诺塔非递归比较局限,只考虑3根柱子A, B, C,且只有A上有 n 个环,要求全移到 C 上。
其他的情况还在探讨中
非递归思想和上面 快速排序非递归 的思想一样

//汉诺塔递归非递归对比算法
#include <iostream>
#include <stack>
using namespace std;

//汉诺塔递归算法
void Hanoi(int n, char A, char B, char C)
{
	if (n <= 0)
		return;
	if (n > 1)
		Hanoi(n - 1, A, C, B);
	cout << '(' << n << ")," << A << ',' << C << endl;
	if (n > 1)
		Hanoi(n - 1, B, A, C);
}
// 汉诺塔非递归算法
void Hanoi2(int n, char A, char B, char C)
{
	if (n <= 0)
		return;
	char a, b, c;
	stack<char> S;
	S.push(A);
	S.push(B);
	S.push(C);
	while (!S.empty())
	{
		c = S.top();
		S.pop();
		b = S.top();
		S.pop();
		a = S.top();
		S.pop();
		cout << '(' << n-1 << ")," << a << ',' << c << endl;
		if (n - 1 > 1)
		{
			S.push(a);
			S.push(c);
			S.push(b);
			n--;
		}
	}
}
//附加验证
int main()
{
	char E = 'A', F = 'B', G = 'C';
	Hanoi(3, E, F, G);
	cout << endl;
	return 0;
}

2. 判断完全二叉树

每个节点有四种情况,根据完全二叉树定义进行 标记或判断
该博文思路相同,讲解详细:https://blog.csdn.net/qq_40938077/article/details/80471997

bool isCBTtree(const BTnode<T>* t)
{
	if (t == NULL) //空树是完全二叉树
		return true;
	queue<const BTnode<T>*> Q;
	Q.push(t);
	bool tag = false;
	while (!Q.empty())
	{
		t = Q.front();
		Q.pop();
		if ((tag && (t->left!=NULL || t->right != NULL)) || (t->left == NULL && t->right != NULL))
			return false;
		if(t->left)
			Q.push(t->left);
		if(t->right)
			Q.push(t->right);
		if(!t->right)
			tag=true;
	}
	return true;
}

3. 二叉链表交换左右孩子

3.1 递归
template <class T>
void ChangLR1(BTnode<T>* t)
{
	if (t->left == NULL && t->right == NULL)
		return;
	BTnode<T>* temp;
	temp = t->left;
	t->left = t->right;
	t->right = temp;
	if (t->left)
		ChangLR1(t->left);
	if (t->right)
		ChangLR1(t->right);
	cout << endl;
}

3.1 非递归
template <class T>
void ChangLR2(BTnode<T>* t)
{
	if (t == NULL)
		return;
	queue <BTnode<T>*> Q;
	Q.push(t);
	BTnode<T>* temp;
	while (!Q.empty())
	{
		t = Q.front();
		Q.pop();
		temp = t->left;
		t->left = t->right;
		t->right = temp;
		if (t->left)
			Q.push(t->left);
		if (t->right)
			Q.push(t->right);
	}
	cout << endl;
}

4. 01背包问题

关于01背包问题,有一篇博文讲的非常妙,看完后把表手动打一遍理解更深刻:https://blog.csdn.net/qq_38410730/article/details/81667885

下面的代码其实还可以模块化,有机会继续改善

#include <iostream>
#include <algorithm>
using namespace std;

int item[5] ;
int w[5] = { 0,2,3,4,5 };
int v[5] = { 0,3,4,5,6 };
int dp[5][9] = { {0} };
int Vbag = 8;

void xuanzhe()
{
	int i, j;
	for(i=1;i<=4;i++)
		for (j = 1; j <= Vbag; j++)
		{
			if (j >= w[i])
			{
				dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - w[i]] + v[i] );
				//item[i] = 1;
			}
			else
			{
				dp[i][j] = dp[i - 1][j];
				//item[i] = 0;
			}
		}
}

void dabiao()
{
	int i, j;
	for (i = 0; i <= 4; i++)
	{ 
		for (j = 0; j <=8; j++)
			cout << dp[i][j] << "  ";
		cout << endl;
	}
	cout << endl;
	for (i = 1; i <= 4; i++)
		cout << item[i] << "  ";
	cout << endl;
}

void zhaoduilie(int i,int j)
{
	if(i >= 0 )
	{
			if (dp[i][j] == dp[i - 1][j])
			{
				item[i] = 0;
				zhaoduilie(i - 1,j);
			}
			if (j - w[i] >= 0 && dp[i][j] == dp[i - 1][j - w[i]] + v[i])
			{
				item[i] = 1;
				zhaoduilie(i - 1,j-w[i]);
			}
	}
}

int main()
{
	xuanzhe();
	zhaoduilie(4,8);
	dabiao();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值