二叉树算法(递归与非递归)

  首先我们来了解下二叉树的基本概念和构造


1.  父节点,子节点,兄弟节点

很容易理解,2和3的父节点就是1,反过来说就是2和3是1的子节点。2和3就是兄弟节点。

2.  结点的度

 其实”度“就是”分支数“,比如1的分支数有两个“2和3",那么1的度为2。

3. 树的度

看似比较莫名其妙吧,他和”结点的度“的区别就是,树的度讲究大局观,乃树中最大的结点度,其实也就是2。

4.叶结点,分支结点

 叶结点就是既没有左孩子也没有右孩子结点,也就是结点度为0。

5. 结点的层数

 这个很简单,也就是树有几层。

6.  森林

现实中,很多的树形成了森林,那在数据结构中,我们把上图的“1”节点砍掉,那么2,3子树合一起就是森林。

7.树的表示

 树这个结构的表示其实有很多种,常用的也就是“括号”表示法。

 比如上面的树就可以表示为:(1(2(4),(5(,7))),3(,6(,8)))

8.树的一些基本算法:下面除了层序遍历的非递归算法用到了队列的知识点,其他的非递归算法基本用到了栈的知识点

    对队列或者是栈不懂得可以点击文字连接了解。

1.创建树

           创建树有两种方式,顺序储存和链表储存。由于顺序储存存在操作不方便,且占用资源多的缺点。故一般我们采 用链表形式来创建一个二叉树。我们需要定义一个二叉树的结构体,在这个结构体中,需要定义两个指针,分别指向左子树和右子树。在这里我们在创建上图二叉树时,一般采取的是按照先左后右的方式创建二叉树。而且我们需要将上图转化为一个数组方便我们进行操作。

typedef int ValueType;

typedef struct Node {
	ValueType value;
	struct Node *LChild;
	struct Node *RChild;
}*BinaryTree;

const ValueType elem[] = { 1,2,4,0,0,5,0,7,0,0,3,0,6,0,8,0,0 };

BinaryTree _Create(const ValueType* &elem) {                      //创建树
	ValueType v = *elem;
	++elem;
	BinaryTree t;
	if (!v) t = NULL;
	else {
		t = new Node;
		t->value = v;
		t->LChild = _Create(elem);
		t->RChild = _Create(elem);
	}
	return t;
}

BinaryTree _Create1(const ValueType *value) {             //创建树,非递归
	const ValueType *v = value;
	BinaryTree node = new Node;
	BinaryTree tree = node;
	stack<BinaryTree> s;
	while (*v || !s.empty()) {
		while (*v) {
			node->value = *v;
			++v;
			s.push(node);
			if (*v) {
				node->LChild = new Node;
				node = node->LChild;
			}
			else node->LChild = NULL;
		}
		BinaryTree top = s.top();
		s.pop();
		++v;
		if (*v) {
			top->RChild = new Node;
			node = top->RChild;
		}
		else top->RChild = NULL;
	}
	return tree;
}


      2.先序遍历

            按先进先出的方式,如上面在创建二叉树是先创建的就先输出来:结果应该为:12457368

void _PreOrder_Traverse(BinaryTree tree) {      //前序遍历
	if (tree) {
		cout << tree->value << " ";
		_PreOrder_Traverse(tree->LChild);
		_PreOrder_Traverse(tree->RChild);
	}
}

void _PreOrder_Traverse1(BinaryTree tree) {               //前序遍历,非递归
	stack<BinaryTree> s;
	Node *node = tree;
	while (node || !s.empty()) {
		while (node) {
			cout << node->value << " ";
			s.push(node);
			node = node->LChild;
		}
		Node *top = s.top();
		s.pop();
		node = top->RChild;
	}
	cout << endl;
}

void _PreOrder_Traverse2(BinaryTree tree) {             //这种方法更加简洁
	stack<BinaryTree> s;
	BinaryTree p = tree;
	while (p || !s.empty()) {
		if (p) {
			cout << p->value << " ";
			s.push(p);
			p = p->LChild;
		}
		else {
			p = s.top();
			s.pop();
			p = p->RChild;
		}
	}
	cout << endl;
}
        3.中序遍历:在输出一个节点后,返回输出该节点的父节点,然后输出父节点的右子树。
void _InOrder_Traverse(BinaryTree tree) {           //中序遍历,递归法
	if (tree) {
		_InOrder_Traverse(tree->LChild);
		cout << tree->value << " ";
		_InOrder_Traverse(tree->RChild);
	}
}

void _InOrder_Traverse1(BinaryTree tree) {      //中序遍历,非递归
	Node *node = tree;
	stack<BinaryTree> s;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
		}
		Node *top = s.top();
		cout << top->value << " ";
		s.pop();
		if (top->RChild != NULL)node = top->RChild;
	}
	cout << endl;
}

void _InOrder_Traverse2(BinaryTree tree) {                  //中序遍历,非递归,简洁版
	stack<BinaryTree> s;
	BinaryTree p = tree;
	while (p || !s.empty()) {
		if (p) {
			s.push(p);
			p = p->LChild;
		}
		else {
            p = s.top();
			s.pop();
			cout << p->value << " ";
			p = p->RChild;
		}
	}
	cout << endl;
}

        3.后序遍历,按照从左往右的方式,先输出一个节点的左右子树,在输出该节点,接着输出该节点的兄弟子树,让后输出该节点的父节点。
void _PostOrder_Traverse(BinaryTree tree) {            //后序遍历,递归法
	if (tree) {
		_PostOrder_Traverse(tree->LChild);
		_PostOrder_Traverse(tree->RChild);
		cout << tree->value << " ";
	}
}

void _PostOrder_Traverse1(BinaryTree tree) {         //后序遍历,非递归法
	Node *node = tree;
	stack<BinaryTree> s;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
		}
		Node *top = s.top();
		if (!top->RChild) {
			cout << top->value << " ";
			s.pop();
			Node *tmp = s.top();
			while (top == tmp->RChild) {
				top = s.top();
				cout << top->value << " ";
				s.pop();
				if (!s.empty())tmp = s.top();
			}
		}
		else {
			top = s.top();
			node = top->RChild;
		}
	}
	cout << endl;
}

         4.层序遍历。顾名思义就是一层一层的输出啦!这里需要用到队列的来解决这个问题。
void _Level_Traverse(BinaryTree tree) {          //层次遍历
	queue<BinaryTree> q;
	BinaryTree tmp = tree;
	q.push(tmp);
	while(!q.empty()) {
		tmp=q.front();
		cout << tmp->value << " ";
		q.pop();
		if (tmp->LChild != NULL)q.push(tmp->LChild);
		if (tmp->RChild != NULL)q.push(tmp->RChild);
	}
}

        5.求深度:就是求这棵树最多有几层
int _Depth(BinaryTree tree) {              //求树的深度,递归法
	if (!tree)return 0;
	else {
		int LDepth = _Depth(tree->LChild);
		int RDepth = _Depth(tree->RChild);
		if (LDepth > RDepth)return 1 + LDepth;
		else return 1 + RDepth;
	}
}

int _Depth1(BinaryTree tree) {          //求树的深度,非递归法
	if (!tree)return 0;
	int depth = 0;
	int flag = 0;               //用于标记正在遍历的在大深度
	stack<BinaryTree> s;
	Node *node = tree;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
			++flag;
		}
		if (flag > depth)depth = flag;          //当某一子树大于已经求得的子树深度时,将深度重赋值
		Node *top = s.top();
		if (top->RChild)node = top->RChild;
		else {
			s.pop();
			Node *tmp = s.top();
			while (top == tmp->RChild&&!s.empty()) {
				top = s.top();
				s.pop();
				--flag;
				if (!s.empty())tmp = s.top();
			}
			--flag;
		}
	}
	return depth;
}

          6.求叶子数,就是求没有左右子树的节点数
int _Leaves(BinaryTree tree) {             //求叶子数,递归法
	if (!tree)return 0;
	BinaryTree tmp = tree;
	int num = 0;
	if (tmp->LChild == NULL&&tmp->RChild == NULL)return num+1;
	if (tmp->LChild != NULL)num += _Leaves(tmp->LChild);
	if (tmp->RChild != NULL)num += _Leaves(tmp->RChild);
	return num;
}

int _Leaves1(BinaryTree tree) {             //求叶子数,非递归
	if (!tree)return 0;
	int leaves = 0;
	BinaryTree node = tree;
	stack<BinaryTree> s;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
			++leaves;
		}
		Node *top = s.top();
		if (!top->RChild) {
			s.pop(); 
			Node *tmp=new Node;
			if (!s.empty()) tmp = s.top();           //防止栈空时赋值
			while (top == tmp->RChild) {
				top = s.top();
				s.pop();
				if(!s.empty())tmp = s.top();
			}
		}
		else node = top->RChild;
	}
	return leaves;
}

        7.求树的大小:树总共有几个节点
int _Size(BinaryTree tree) {                     //求树的大小 ,递归法
	if (!tree) return 0;
	else return 1 + _Size(tree->LChild) + _Size(tree->RChild);
}

int _Size1(BinaryTree tree) {              //求树的大小 ,非递归法
	if (!tree)return 0;
	int size = 0;
	stack<BinaryTree> s;
	Node *node = tree;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
			++size;
		}
		Node *top = s.top();
		s.pop();
		node = top->RChild;
	}
	return size;
}
            8.拷贝。没啥好说的,就是拷贝一个新的树出来。
BinaryTree _Copy1(BinaryTree tree) {       //拷贝,非递归
	if (!tree) return NULL;
	BinaryTree n_tree;
	BinaryTree n_node = new Node;
	n_tree = n_node;
	BinaryTree prev = tree;
	stack<BinaryTree> s;
	stack<BinaryTree> n_s;
	while (prev || !s.empty()) {
		while (prev) {
			n_node->value = prev->value;
			s.push(prev);
			n_s.push(n_node);
			prev = prev->LChild;
			if (!prev)n_node->LChild = NULL;
			else {
				n_node->LChild = new Node;
				n_node = n_node->LChild;
			}
		}
		BinaryTree top = s.top();
		BinaryTree n_top = n_s.top();
		s.pop();
		n_s.pop();
		if (!top->RChild)n_top->RChild = NULL;
		else {
			n_top->RChild = new Node;
			n_node = n_top->RChild;
			prev = top->RChild;
		}
	}
	return n_tree;
}

         9.反转二叉树,这个算法可是有个有趣的故事,直接从网上截图过来:
BinaryTree _InverseTree(BinaryTree tree) {            //翻转二叉树,递归
	if (!tree) return NULL;
	Node *n_tree = new Node;
	n_tree->value = tree->value;
	n_tree->LChild = _InverseTree(tree->RChild);
	n_tree->RChild = _InverseTree(tree->LChild);
	return n_tree;
}

BinaryTree _InverseTree1(BinaryTree tree) {        //翻转二叉树,非递归
	if (!tree) return NULL;
	BinaryTree n_tree;
	BinaryTree n_node = new Node;
	n_tree = n_node;
	BinaryTree prev = tree;
	stack<BinaryTree> s;
	stack<BinaryTree> n_s;
	while (prev || !s.empty()) {
		while (prev) {
			n_node->value = prev->value;
			s.push(prev);
			n_s.push(n_node);
			prev = prev->RChild;
			if (!prev)n_node->LChild = NULL;
			else {
				n_node->LChild = new Node;
				n_node = n_node->LChild;
			}
		}
		BinaryTree top = s.top();
		BinaryTree n_top = n_s.top();
		s.pop();
		n_s.pop();
		if (!top->LChild)n_top->RChild = NULL;
		else {
			n_top->RChild = new Node;
			n_node = n_top->RChild;
			prev = top->LChild;
		}
	}
	return n_tree;
}

好了,经常会用到的一些操作的算法就是这么一些了。当然,以后我会尽量收集二叉树的一些题目。最后献上运行结果以及源代码吧。

#include<iostream>
#include<queue>
#include<stack>
using namespace std;

typedef int ValueType;

typedef struct Node {
	ValueType value;
	struct Node *LChild;
	struct Node *RChild;
}*BinaryTree;

BinaryTree _Create(const ValueType* &elem) {                      //创建树
	ValueType v = *elem;
	++elem;
	BinaryTree t;
	if (!v) t = NULL;
	else {
		t = new Node;
		t->value = v;
		t->LChild = _Create(elem);
		t->RChild = _Create(elem);
	}
	return t;
}

BinaryTree _Create1(const ValueType *value) {             //创建树,非递归
	const ValueType *v = value;
	BinaryTree node = new Node;
	BinaryTree tree = node;
	stack<BinaryTree> s;
	while (*v || !s.empty()) {
		while (*v) {
			node->value = *v;
			++v;
			s.push(node);
			if (*v) {
				node->LChild = new Node;
				node = node->LChild;
			}
			else node->LChild = NULL;
		}
		BinaryTree top = s.top();
		s.pop();
		++v;
		if (*v) {
			top->RChild = new Node;
			node = top->RChild;
		}
		else top->RChild = NULL;
	}
	return tree;
}

void _PreOrder_Traverse(BinaryTree tree) {      //前序遍历
	if (tree) {
		cout << tree->value << " ";
		_PreOrder_Traverse(tree->LChild);
		_PreOrder_Traverse(tree->RChild);
	}
}

void _PreOrder_Traverse1(BinaryTree tree) {               //前序遍历
	stack<BinaryTree> s;
	Node *node = tree;
	while (node || !s.empty()) {
		while (node) {
			cout << node->value << " ";
			s.push(node);
			node = node->LChild;
		}
		Node *top = s.top();
		s.pop();
		node = top->RChild;
	}
	cout << endl;
}

void _PreOrder_Traverse2(BinaryTree tree) {             //这种方法更加简洁
	stack<BinaryTree> s;
	BinaryTree p = tree;
	while (p || !s.empty()) {
		if (p) {
			cout << p->value << " ";
			s.push(p);
			p = p->LChild;
		}
		else {
			p = s.top();
			s.pop();
			p = p->RChild;
		}
	}
	cout << endl;
}

void _InOrder_Traverse(BinaryTree tree) {           //中序遍历,递归法
	if (tree) {
		_InOrder_Traverse(tree->LChild);
		cout << tree->value << " ";
		_InOrder_Traverse(tree->RChild);
	}
}

void _InOrder_Traverse1(BinaryTree tree) {      //中序遍历,非递归
	Node *node = tree;
	stack<BinaryTree> s;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
		}
		Node *top = s.top();
		cout << top->value << " ";
		s.pop();
		if (top->RChild != NULL)node = top->RChild;
	}
	cout << endl;
}

void _InOrder_Traverse2(BinaryTree tree) {                  //中序遍历,非递归,简洁版
	stack<BinaryTree> s;
	BinaryTree p = tree;
	while (p || !s.empty()) {
		if (p) {
			s.push(p);
			p = p->LChild;
		}
		else {
            p = s.top();
			s.pop();
			cout << p->value << " ";
			p = p->RChild;
		}
	}
	cout << endl;
}

void _PostOrder_Traverse(BinaryTree tree) {            //后序遍历,递归法
	if (tree) {
		_PostOrder_Traverse(tree->LChild);
		_PostOrder_Traverse(tree->RChild);
		cout << tree->value << " ";
	}
}

void _PostOrder_Traverse1(BinaryTree tree) {         //后序遍历,非递归法
	Node *node = tree;
	stack<BinaryTree> s;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
		}
		Node *top = s.top();
		if (!top->RChild) {
			cout << top->value << " ";
			s.pop();
			Node *tmp = s.top();
			while (top == tmp->RChild) {
				top = s.top();
				cout << top->value << " ";
				s.pop();
				if (!s.empty())tmp = s.top();
			}
		}
		else {
			top = s.top();
			node = top->RChild;
		}
	}
	cout << endl;
}

void _Level_Traverse(BinaryTree tree) {          //层次遍历
	queue<BinaryTree> q;
	BinaryTree tmp = tree;
	q.push(tmp);
	while(!q.empty()) {
		tmp=q.front();
		cout << tmp->value << " ";
		q.pop();
		if (tmp->LChild != NULL)q.push(tmp->LChild);
		if (tmp->RChild != NULL)q.push(tmp->RChild);
	}
}

int _Depth(BinaryTree tree) {              //求树的深度,递归法
	if (!tree)return 0;
	else {
		int LDepth = _Depth(tree->LChild);
		int RDepth = _Depth(tree->RChild);
		if (LDepth > RDepth)return 1 + LDepth;
		else return 1 + RDepth;
	}
}

int _Depth1(BinaryTree tree) {          //求树的深度,非递归法
	if (!tree)return 0;
	int depth = 0;
	int flag = 0;               //用于标记正在遍历的在大深度
	stack<BinaryTree> s;
	Node *node = tree;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
			++flag;
		}
		if (flag > depth)depth = flag;          //当某一子树大于已经求得的子树深度时,将深度重赋值
		Node *top = s.top();
		if (top->RChild)node = top->RChild;
		else {
			s.pop();
			Node *tmp = s.top();
			while (top == tmp->RChild&&!s.empty()) {
				top = s.top();
				s.pop();
				--flag;
				if (!s.empty())tmp = s.top();
			}
			--flag;
		}
	}
	return depth;
}

int _Size(BinaryTree tree) {                     //求树的大小 ,递归法
	if (!tree) return 0;
	else return 1 + _Size(tree->LChild) + _Size(tree->RChild);
}

int _Size1(BinaryTree tree) {              //求树的大小 ,非递归法
	if (!tree)return 0;
	int size = 0;
	stack<BinaryTree> s;
	Node *node = tree;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
			++size;
		}
		Node *top = s.top();
		s.pop();
		node = top->RChild;
	}
	return size;
}

int _Leaves(BinaryTree tree) {             //求叶子数,递归法
	if (!tree)return 0;
	BinaryTree tmp = tree;
	int num = 0;
	if (tmp->LChild == NULL&&tmp->RChild == NULL)return num+1;
	if (tmp->LChild != NULL)num += _Leaves(tmp->LChild);
	if (tmp->RChild != NULL)num += _Leaves(tmp->RChild);
	return num;
}

int _Leaves1(BinaryTree tree) {             //求叶子数,非递归
	if (!tree)return 0;
	int leaves = 0;
	BinaryTree node = tree;
	stack<BinaryTree> s;
	while (node || !s.empty()) {
		while (node) {
			s.push(node);
			node = node->LChild;
			++leaves;
		}
		Node *top = s.top();
		if (!top->RChild) {
			s.pop(); 
			Node *tmp=new Node;
			if (!s.empty()) tmp = s.top();           //防止栈空时赋值
			while (top == tmp->RChild) {
				top = s.top();
				s.pop();
				if(!s.empty())tmp = s.top();
			}
		}
		else node = top->RChild;
	}
	return leaves;
}

BinaryTree _Copy(BinaryTree tree) {      //拷贝
	if (!tree)return NULL;
	BinaryTree p = tree;
	BinaryTree n_tree = new Node;
	n_tree->value = p->value;
	n_tree->LChild = _Copy(p->LChild);
	n_tree->RChild = _Copy(p->RChild);
	return n_tree;
}

BinaryTree _Copy1(BinaryTree tree) {       //拷贝,非递归
	if (!tree) return NULL;
	BinaryTree n_tree;
	BinaryTree n_node = new Node;
	n_tree = n_node;
	BinaryTree prev = tree;
	stack<BinaryTree> s;
	stack<BinaryTree> n_s;
	while (prev || !s.empty()) {
		while (prev) {
			n_node->value = prev->value;
			s.push(prev);
			n_s.push(n_node);
			prev = prev->LChild;
			if (!prev)n_node->LChild = NULL;
			else {
				n_node->LChild = new Node;
				n_node = n_node->LChild;
			}
		}
		BinaryTree top = s.top();
		BinaryTree n_top = n_s.top();
		s.pop();
		n_s.pop();
		if (!top->RChild)n_top->RChild = NULL;
		else {
			n_top->RChild = new Node;
			n_node = n_top->RChild;
			prev = top->RChild;
		}
	}
	return n_tree;
}

BinaryTree _InverseTree(BinaryTree tree) {            //翻转二叉树,递归
	if (!tree) return NULL;
	Node *n_tree = new Node;
	n_tree->value = tree->value;
	n_tree->LChild = _InverseTree(tree->RChild);
	n_tree->RChild = _InverseTree(tree->LChild);
	return n_tree;
}

BinaryTree _InverseTree1(BinaryTree tree) {        //翻转二叉树,非递归
	if (!tree) return NULL;
	BinaryTree n_tree;
	BinaryTree n_node = new Node;
	n_tree = n_node;
	BinaryTree prev = tree;
	stack<BinaryTree> s;
	stack<BinaryTree> n_s;
	while (prev || !s.empty()) {
		while (prev) {
			n_node->value = prev->value;
			s.push(prev);
			n_s.push(n_node);
			prev = prev->RChild;
			if (!prev)n_node->LChild = NULL;
			else {
				n_node->LChild = new Node;
				n_node = n_node->LChild;
			}
		}
		BinaryTree top = s.top();
		BinaryTree n_top = n_s.top();
		s.pop();
		n_s.pop();
		if (!top->LChild)n_top->RChild = NULL;
		else {
			n_top->RChild = new Node;
			n_node = n_top->RChild;
			prev = top->LChild;
		}
	}
	return n_tree;
}

void test() {
	BinaryTree root;
	root = new Node;
	const ValueType elem[] = { 1,2,4,0,0,5,0,7,0,0,3,0,6,0,8,0,0 };
	const ValueType *p = elem;
	root = _Create1(p);
	_PreOrder_Traverse(root);
	cout << endl;
	_PreOrder_Traverse1(root);
	_PreOrder_Traverse2(root);
	_InOrder_Traverse(root);
	cout << endl;
	_InOrder_Traverse1(root);
	_InOrder_Traverse2(root);
	_PostOrder_Traverse(root);
	cout << endl;
	_PostOrder_Traverse1(root);
	_Level_Traverse(root);
	cout << endl;
	cout << "Leaves:" << _Leaves(root) << endl;
	cout << "Leaves:" << _Leaves1(root) << endl;
	cout << "Depth:" << _Depth(root) << endl;
	cout << "Depth:" << _Depth1(root) << endl;
	cout << "Size:" << _Size(root) << endl;
	cout << "Size:" << _Size1(root) << endl;
	BinaryTree tree1 = _Copy(root);
	_PreOrder_Traverse1(tree1);
	BinaryTree tree2 = _Copy1(root);
	_PreOrder_Traverse1(tree2);
	BinaryTree tree3 = _InverseTree(root);
	_PreOrder_Traverse1(tree3);
	BinaryTree tree4 = _InverseTree1(root);
	_PreOrder_Traverse1(tree4);
	cout << endl;
}

void main() {
	test();
	system("pause");
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值