输出具有n个结点的所有不同的二叉树-增强前序遍历形式输出-C++

        我们知道具有n个结点的不同的二叉树的数量是\frac{\binom{n}{2n}}{n+1}个(这是一个卡塔兰数),那么如何确定这些二叉树是什么样子的呢?下面是博主的思路:

        我们还知道一个入栈序列的不同出栈序列的数量也是\frac{\binom{n}{2n}}{n+1}个,于是博主就想:这不是巧了么,既然他们的数量是一样的,而且均不相同,那么是不是可以构建一个映射,使得不同的出栈序列和不同的二叉树进行一一对应呢。

        于是,在博主的做了深入的观察和思考后,发现对于其中一个出栈序列,其实和某个二叉树的中序遍历结果是相对应的,而经过进一步探索,发现入栈序列是所有二叉树的前序遍历结果。

        众所周知,一个二叉树的前序和中序遍历结果是可以唯一确定一棵二叉树的。

        然而在写代码的过程中博主又遇到了一个难题:就是如何输出一个入栈序列的全部出栈序列呢?为了解决这个问题,博主上某搜索网站参考了各位大神的代码,发现他们基本都是用回溯法解决的。于是在一番研究之下。我成功地写出了输出一个入栈序列的全部出栈序列的函数。

        这样一来,所有问题都解决了。然后经过了20分钟的编码。博主成功地写出了求解具有n个结点的不同的二叉树的所有前序增强序列的C++代码:

        另外如果大家有什么疑问或者见解可以在评论下方讨论,如果发现确实有什么错误的话,还请指正。

如下所示:

#include <iostream>

using namespace std;

static const int M = 100;
//依次代表的意思是结点数、栈、出栈序列、栈指针、出栈序列大小、输入顺序、二叉树中序序列,二叉树中序序列索引
static int n,stk[M],seq[M],stk_top=-1,seq_size=0,input[M],in[M],idx;

//根据二叉树的前序和中序遍历获取增强前序序列
static void getEnhencedPreorder(int root, int begin, int end) {
	if (begin > end) {
		cout << "#" << " ";
		return;
	}
	int i = begin;
	while (input[root] != in[i]) {
		i++;
	}
	cout << input[root] << " ";
	getEnhencedPreorder(root + 1, begin, i - 1);
	getEnhencedPreorder(root + (i - begin) + 1, i + 1, end);
}

//获取所有出栈序列
static void getSequence(int i) {
	if (i == n) {
		//收集结果
		idx = 0;
		for (int i = 0; i < seq_size; i++) {
			in[idx++]=seq[i];
		}
		for (int i = stk_top; i >= 0; i--) {
			in[idx++] = stk[i];
		}
		//根据前序和中序遍历获取其增强前序遍历序列
		getEnhencedPreorder(0,0,n-1);
		cout << endl;
	} else {
		//对于一个入栈的元素,可以入栈,也可以不入栈
		//但是每种情况都要检验

		//一、首先是元素入栈了
		stk[++stk_top]= input[i];
		getSequence(i + 1);
		stk_top--;

		//二、然后元素没有入栈,并且栈顶元素出栈了
		if (stk_top!=-1) {
			int top= stk[stk_top--];
			seq[seq_size++]=top;
			getSequence(i);
			seq_size--;
			stk[++stk_top] = top;
		}
	}
}

//相当于main函数
void stack_pop_sequence_re2_main() {
	cin >> n;
	for (int i = 0; i < n;i++) {
		input[i] = i + 1;
	}
	getSequence(0);
}

下面是一个示例(当n取3时):

其入栈序列为1 2 3,输出结果为所有组成的二叉树的前序增强序列('#'号标识空)。

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,下面是使用 C 语言实现二叉树代码,包括前序遍历、中序遍历和后序遍历的输出。 ```c #include <stdio.h> #include <stdlib.h> struct node { int data; struct node* left; struct node* right; }; struct node* create_node(int value) { struct node* new_node = (struct node*) malloc(sizeof(struct node)); new_node->data = value; new_node->left = NULL; new_node->right = NULL; return new_node; } struct node* insert_node(struct node* root, int value) { if (root == NULL) { return create_node(value); } else if (value < root->data) { root->left = insert_node(root->left, value); } else { root->right = insert_node(root->right, value); } return root; } void preorder_traversal(struct node* root) { if (root != NULL) { printf("%d ", root->data); preorder_traversal(root->left); preorder_traversal(root->right); } } void inorder_traversal(struct node* root) { if (root != NULL) { inorder_traversal(root->left); printf("%d ", root->data); inorder_traversal(root->right); } } void postorder_traversal(struct node* root) { if (root != NULL) { postorder_traversal(root->left); postorder_traversal(root->right); printf("%d ", root->data); } } int main() { struct node* root = NULL; root = insert_node(root, 5); insert_node(root, 3); insert_node(root, 7); insert_node(root, 1); insert_node(root, 4); insert_node(root, 6); insert_node(root, 8); printf("Preorder traversal: "); preorder_traversal(root); printf("\n"); printf("Inorder traversal: "); inorder_traversal(root); printf("\n"); printf("Postorder traversal: "); postorder_traversal(root); printf("\n"); return 0; } ``` 运行结果: ``` Preorder traversal: 5 3 1 4 7 6 8 Inorder traversal: 1 3 4 5 6 7 8 Postorder traversal: 1 4 3 6 8 7 5 ``` 上面的代码中,我们首先定义了一个二叉树节点结构体 `node`,其中包含节点值 `data`,以及左右子节点指针 `left` 和 `right`。然后,我们定义了 `create_node` 函用于创建新节点,并为其赋初值;`insert_node` 函用于向二叉树中插入新节点。 接下来,我们定义了三个遍历函,分别是前序遍历、中序遍历和后序遍历。这三个遍历函的实现都比较简单,都是递归调用自身,然后按照遍历顺序输出当前节点的值。最后,在 `main` 函中,我们创建了一个二叉树,并进行了前序、中序和后序遍历,输出遍历的结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Kirito

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值