二叉树遍历算法总结(剑指offer23、编程之美3.10)

1.二叉树结点的数据结构

struct BinaryTreeNode {
	char m_chChildTag; //后序遍历时用于标识其最新一次访问的是左孩子还是右孩子
	char m_chData; //用于遍历时存储结点字符
	int m_nValue; //用于结点是整数数值的情况
	BinaryTreeNode* m_pLeftChild;
	BinaryTreeNode* m_pRightChild;
};

2.创建二叉树(结点值是一个字符)

BinaryTreeNode* createCharBinaryTree() {
	BinaryTreeNode* binaryTreeNode;
	char ch = '#';
	cin >> ch;
	if ('#' != ch) {
		binaryTreeNode = new BinaryTreeNode();
		binaryTreeNode->m_chData = ch;
		binaryTreeNode->m_pLeftChild = createCharBinaryTree();
		binaryTreeNode->m_pRightChild = createCharBinaryTree();
	} else {
		binaryTreeNode = NULL;
	}

	return binaryTreeNode;
}

3.创建二叉树(结点值是一个整型变量)

BinaryTreeNode* createIntBinaryTree() {
	BinaryTreeNode* binaryTreeNode;
	int data = 0;
	cin >> data;
	if (0 != data) {
		binaryTreeNode = new BinaryTreeNode();
		binaryTreeNode->m_nValue = data;
		binaryTreeNode->m_pLeftChild = createIntBinaryTree();
		binaryTreeNode->m_pRightChild = createIntBinaryTree();
	} else {
		binaryTreeNode = NULL;
	}

	return binaryTreeNode;
}

4.前序遍历(递归式)

void preorderTravesal(BinaryTreeNode* rootNode) {
	if (NULL != rootNode) {
		cout << rootNode->m_chData << "\t";
		preorderTravesal(rootNode->m_pLeftChild);
		preorderTravesal(rootNode->m_pRightChild);
	}
}

5.中序遍历(递归式)

void inorderTravesal(BinaryTreeNode* rootNode) {
	if (NULL != rootNode) {
		inorderTravesal(rootNode->m_pLeftChild);
		cout << rootNode->m_chData << "\t";
		inorderTravesal(rootNode->m_pRightChild);
	}
}

6.后序遍历(递归式)

void postorderTravesal(BinaryTreeNode* rootNode) {
	if (NULL != rootNode) {
		postorderTravesal(rootNode->m_pLeftChild);
		postorderTravesal(rootNode->m_pRightChild);
		cout << rootNode->m_chData << "\t";
	}
}

7.前序遍历(非递归式)

void preorderTravesal_loop(BinaryTreeNode* rootNode) {
	if (NULL == rootNode) {
		return;
	}

	std::stack<BinaryTreeNode*> stack;
	BinaryTreeNode* p = rootNode;

	stack.push(p);
	while (NULL != p || !stack.empty()) {
		//找到最左孩子
		while (NULL != p) {
			//入栈前输出
			if (p->m_chData) {
				cout << p->m_chData << "\t";
			} else {
				cout << p->m_nValue << "\t";
			}

			p = p->m_pLeftChild;
			stack.push(p);
		}

		//弹出最左空孩子
		stack.pop();

		if (!stack.empty()) {
			BinaryTreeNode* q = stack.top();
			stack.pop();
			//将当前结点的右孩子入栈
			stack.push(q->m_pRightChild);
			p = q->m_pRightChild;
		}
	}
}

8.中序遍历(非递归式)

void inorderTravesal_loop(BinaryTreeNode* rootNode) {
	if (NULL == rootNode) {
		return;
	}

	std::stack<BinaryTreeNode*> stack;
	BinaryTreeNode* p = rootNode;

	stack.push(p);
	while (p != NULL || !stack.empty()) {
		//找到最左孩子
		while (p != NULL) {
			p = p->m_pLeftChild;
			stack.push(p);
		}

		//弹出最左空孩子
		stack.pop();

		if (!stack.empty()) {
			BinaryTreeNode *q = stack.top();
			//出栈前输出
			cout << q->m_chData << "\t";
			stack.pop();

			//将当前结点的右孩子入栈
			stack.push(q->m_pRightChild);
			p = q->m_pRightChild;
		}
	}

}

9.后序遍历(非递归式)--需要标记是访问父结点时是从左孩子还是右孩子来的,标记的时候可以将二叉树结点结构体中添加一个标志或者另外用一个栈来同步这个标志

void postorderTravesal_loop(BinaryTreeNode* rootNode) {
	if (NULL == rootNode) {
		return;
	}

	std::stack<BinaryTreeNode*> stack;
	BinaryTreeNode* p = rootNode;
	stack.push(p);
	while (p != NULL || !stack.empty()) {
		while (p != NULL) {
			p->m_chChildTag = 'L';
			p = p->m_pLeftChild;
			stack.push(p);
		}

		stack.pop();

		while (!stack.empty() && stack.top()->m_chChildTag == 'R') {
			cout << stack.top()->m_chData << '\t';
			stack.pop();
		}

		if (!stack.empty()) {
			BinaryTreeNode* q = stack.top();
			q->m_chChildTag = 'R';
			stack.push(q->m_pRightChild);
			p = q->m_pRightChild;
		}
	}
}

10.后序遍历

vector<int> postorderTraversal(TreeNode *root) {
        vector<int> result;
        
        if(NULL == root){
            return result;
        }
        
        TreeNode* p = root;
        TreeNode* preNode = NULL;
        stack<TreeNode*> stack;
        while(NULL != p || !stack.empty()){
            if(NULL != p){
                stack.push(p);
                p = p->left;
            }else{
                p = stack.top();
                if(NULL != p->right && preNode != p->right){
                    p = p->right;
                }else{
                    result.push_back(p->val);
                    
                    preNode = p;
                    stack.pop();
                    p = NULL;
                }
            }
        }
        
        return result;
    }

11.层次遍历

void levelTravesal(BinaryTreeNode* rootNode) {
	if (NULL == rootNode) {
		return;
	}

	std::queue<BinaryTreeNode*> queue;
	BinaryTreeNode* p = rootNode;

	queue.push(p);
	while (!queue.empty()) {
		//取队头输出并删除队头
		BinaryTreeNode* q = queue.front();
		cout << q->m_chData << "\t";
		queue.pop();

		//左孩子不空时入队
		if (q->m_pLeftChild) {
			queue.push(q->m_pLeftChild);
		}

		//右孩子不空时入队
		if (q->m_pRightChild) {
			queue.push(q->m_pRightChild);
		}
	}
}

12.测试代码

#include <stddef.h>
#include <iostream>

using namespace std;

int main() {
	BinaryTreeNode* binaryTreeNode = NULL;

	binaryTreeNode = createCharBinaryTree();

	cout << "二叉树的前序遍历(递归):" << endl;
	preorderTravesal(binaryTreeNode);
	cout << endl;

	cout << "二叉树的中序遍历(递归):" << endl;
	inorderTravesal(binaryTreeNode);
	cout << endl;

	cout << "二叉树的后序遍历(递归):" << endl;
	postorderTravesal(binaryTreeNode);
	cout << endl;

	cout << "二叉树的前序遍历(非递归):" << endl;
	preorderTravesal_loop(binaryTreeNode);
	cout << endl;

	cout << "二叉树的中序遍历(非递归):" << endl;
	inorderTravesal_loop(binaryTreeNode);
	cout << endl;

	cout << "二叉树的后序遍历(非递归):" << endl;
	postorderTravesal_loop(binaryTreeNode);
	cout << endl;

	cout << "二叉树的层次遍历:" << endl;
	levelTravesal(binaryTreeNode);
	cout << endl;

	return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值