二叉树的非递归遍历

typedef struct NodeType{
   int data;
   struct NodeType* left;
   struct NodeType* right;
   NodeType(){left = NULL;right = NULL;};
}Node;

const int MAX = 100;
Node* stack[MAX];
int top = -1;
int tag[MAX];


1 前序遍历

  从根节点开始的所有的左结点依次入栈,然后从root的左子树的左叶子结点开始回溯,那么此左叶子结点一定没有左子结点,可能会有右子结点。该回溯节点出栈后,将它的右子结点当作根结点,重复上述动作。

void PreOrder(Node* root)
{
	while (NULL != root ||
		top >= 0) {

			while (NULL != root) {
				cout << root->data << endl;
				top++;
				stack[top] = root;
				root = root->left;
			}

			//从root的左子树的左叶子节点开始回溯
			if (top >= 0) {
				Node* cur = stack[top];
				top--;//回溯完后即出栈
				root = cur->right;
			}
	}
}

2 中序遍历
  与前序遍历基本一样,root表示需要入栈的根节点,当root为NULL,并且栈为空时,结束遍历。即所有的树节点都已经入栈过,并且最后都通过回溯的方式出栈了,则表示遍历结束。

void InOrder(Node* root)
{
	while (NULL != root ||
		top >= 0) {

			while (NULL != root) {
				top++;
				stack[top] = root;
				root = root->left;
			}

			//从root的左子树的左叶子节点开始回溯
			if (top >=0) {
				Node* cur = stack[top];
				cout << cur->data << endl;
				top--;//回溯完后即出栈
				root = cur->right;
			}
	}
}

3 后序遍历
  从根节点开始的所有的左结点依次入栈,然后将最后一个入栈的左子结点开始回溯。但是入栈的这些左子结点都会被回溯两次。一次是从左子结点返回,一次是从右子结点返回。第一次回溯到该结点不能出栈,必须要先访问其右子结点(可以看作一个根结点,重复上述访问步骤),等到其右子树访问完了后再次回溯到该左子结点时,才能真正出栈。
void PostOrder(Node* root)
{
	while (NULL != root ||
		top >= 0) {

			while (NULL != root) {
				top++;
				stack[top] = root;
				tag[top] = 0;//默认root的右节点没有访问过(算法保证回溯到root时,则它的左节点一定是访问过的)
				root = root->left;
			}

			//从roo的t左子树的左叶子节点开始回溯
			if (top >= 0) {
				Node* cur = stack[top];
				if (1 == tag[top]) {
					cout << cur->data << endl;
					top--;//第二次回溯到该节点后出栈
				} else {
					//第一回溯到该节点暂时不出栈
					root = cur->right;
					tag[top] = 1;//标识root的右节点已经访问过
				}
			}

	}

}


你可能感兴趣的:(二叉树的非递归遍历)