zoukankan      html  css  js  c++  java
  • 算法导论:第10章

    10.4-5 O(n)非递归O(1)空间遍历二叉树树节点

    转自http://blog.csdn.net/mishifangxiangdefeng/article/details/7708490

    采用类似中序遍历的处理方法,对一个结点,可以分为以下几种情况

    1.从父结点进入子结点进行处理

    (1)如果有左孩子,就处理左孩子

    (2)返回到自己

    (3)访问自己

    (4)如果有右孩子,就处理右孩子

    (5)返回到自己的父结点

    2.从左孩子返回,说明左孩子已经处理过,自己还没访问,自己的右孩子也没有处理过,就进行1-(2)

    3.从右孩子返回,说明左右孩子都已经处理,自己也访问过,就返回到更上层

    4.返回到根结点时,遍历结束

    #include <iostream>
    using namespace std;
    
    //二叉树结点的结构体
    struct node
    {
    	int key;//值
    	node *left;//指向左孩子
    	node *right;//指向右孩子
    	node(){}//默认构造函数
    	node(int x):key(x),left(NULL),right(NULL){}//构造函数
    };
    //树的结构体
    struct tree
    {
    	node *root;//树中只有一个指向根结点的指针
    	tree():root(NULL){}//构造函数
    };
    /************10.4-2-递归地遍历访问二叉树***************************************/
    //输出访问某个结点
    void Node_Print(node *N)
    {
    	//访问当前结点
    	cout<<N->key<<' ';
    	//递归地访问其左孩子
    	if(N->left)
    		Node_Print(N->left);
    	//递归地访问其右孩子
    	if(N->right)
    		Node_Print(N->right);
    }
    //遍历二叉树
    void Tree_Print(tree *T)
    {
    	//只孩子访问根结点,其它结点都在递归中访问了
    	Node_Print(T->root);
    	cout<<endl;
    }
    /*************10.4-3-非递归地遍历二叉树*******************************************/
    //把x结点压入栈S的顶部
    void Push(node *S, node x)
    {
    	S[0].key++;
    	S[S[0].key] = x;
    }
    //弹出栈顶元素并返回
    node* Pop(node *S)
    {
    	if(S[0].key == 0)
    		return NULL;
    	node *ret = &S[S[0].key];
    	S[0].key--;
    	return ret;
    }
    //用非递归的方式遍历二叉树
    void Tree_Print2(tree *T)
    {
    	//这种方式要借助一个栈来实现,栈的大小为树的深度
    	node Stack[15] = {0};//简单的数组栈,Stack[0]存储栈顶位置
    	node *t = T->root;
    	//当处理一个结点时,做如下处理
    	while(1)
    	{
    		//访问这个结点
    		cout<<t->key<<' ';
    		//入栈
    		Push(Stack, *t);
    		//如果有左孩子,下一步处理其左孩子
    		if(t->left)
    			t = t->left;
    		//如果没有左孩子
    		else
    		{
    			do{
    				//弹出栈顶元素
    				t = Pop(Stack);
    				//若栈中元素已经全部弹出,那么二叉树访问结束了
    				if(t == NULL)
    				{
    					cout<<endl;
    					return;
    				}
    			}
    			//如果这个栈顶元素没有右孩子,则继续出栈,直到访问结束或找到一个有右孩子的元素
    			while(t->right == NULL);
    			//如果这个栈顶元素有右孩子,则访问其右孩子
    			t = t->right;
    		}
    	}
    }
    /*input:0=NIL
    12 7 3
    15 8 0
    4 10 0
    10 5 9
    2 0 0
    18 1 4
    7 0 0
    14 6 2
    21 0 0
    5 0 0
    */
    int main()
    {
    	//构造一棵树按照10.4-1
    	int i;
    	node A[11];//这个数组仅仅用于构造10.4-1中的树,在遍历时不使用
    	for(i = 1; i <= 10; i++)
    	{
    		int key, left, right;
    		cin>>key>>left>>right;
    		A[i].key = key;
    		if(left)
    			A[i].left = &A[left];
    		else A[i].left = NULL;
    		if(right)
    			A[i].right = &A[right];
    		else A[i].right = NULL;
    	}
    	//生成一棵树
    	tree *T = new tree();
    	T->root = &A[6];
    	//10.4-2,递归方式
    	Tree_Print(T);
    	//10.4-3,非递归方式
    	Tree_Print2(T);
    	return 0;
    }
    

      

  • 相关阅读:
    帝国cms字母导航功能制作教程
    HTML 学习
    DOM
    C# DataTable 使用原创
    GridView中编辑状态下实现DropDownList默认值(原创)
    C#精髓 GridView72大绝技(清清月儿)
    SQL注入攻击<收藏>
    Web网页安全色谱<收藏>
    GridView根据linkButton值不同跳转不同页面(原创)
    解决"Failed to access IIS metabase"
  • 原文地址:https://www.cnblogs.com/rolling-stone/p/3667227.html
Copyright © 2011-2022 走看看