用栈来实现深度优先搜索

栈是一种后入先出(LIFO)的数据结构。可以把栈想象成一个羽毛球桶,只有一个开口,最先放进去的羽毛球会在最里面,而最后放进去的羽毛球会在最外面。当我们拿出羽毛球时会先从最外面开始拿,也就是拿的最后放入的羽毛球。

用栈来完成二叉树的三种遍历

以下练习题均来自于leetcode

二叉树的前序遍历

在这里插入图片描述

思路:用数组来替代栈,首先是根节点入栈。从栈里面取出一个元素,用一个指针指向这个元素,只要这个元素不为空,就一直指向这个元素的左节点,路上挨个输出节点的字,碰到右节点不为空的时候就把右节点压入栈里。一直循环到栈里没有元素为止。

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    struct TreeNode **TreeStack,*p;
    int *val=NULL,index=0,size=0;

    TreeStack=calloc(sizeof(struct TreeNode*),101);

    TreeStack[index++]=root;//根节点入栈
    while(index!=0)
    {
        p=TreeStack[index-1];
        index--;
        while(p)
        {
            size++;
            val=realloc(val,sizeof(int)*size);
            val[size-1]=p->val;
            if(p->right)
            {
                TreeStack[index++]=p->right;
            }
            p=p->left;
        }
        
    }
    free(TreeStack);
    *returnSize=size;
    return val;
}

二叉树的中序遍历

在这里插入图片描述

思路:和上题类似,不同的是进栈顺序,前序遍历中遇到有右节点就进栈。而中序遍历一直进栈左节点,直到左节点为空,再输出该节点的值,然后进栈该节点的右节点。一直循环到栈里没有元素为止。

int* inorderTraversal(struct TreeNode* root, int* returnSize){
    struct TreeNode **TreeStack,*p;
    int *val=NULL,index=0,size=0;

    TreeStack=calloc(sizeof(struct TreeNode*),101);
    TreeStack[index++]=root;//根节点入栈
    while(index!=0)
    {
        p=TreeStack[index-1];
        while(p)//遍历到左节点空
        {
            TreeStack[index++]=p->left;
            p=p->left;
        }
        index--;//将空节点删除
        if(index==0)break;
        size++;
        val=realloc(val,sizeof(int)*size);
        val[size-1]=TreeStack[index-1]->val;
        TreeStack[index-1]=TreeStack[index-1]->right;//将左节点出栈,右节点入栈
    }
    *returnSize=size;
    return val;
}

二叉树的后序遍历

在这里插入图片描述

思路:与前面不同的是,后续遍历要先一直走到左叶子节点后(过程中经历的节点都要依次进栈),再指向右叶子节点,如果为空就输出该节点的值并弹出该节点,然后用一个变量记录下该输出的节点。如果不为空,且与上次输出的节点不同就将该右节点进栈。

int* postorderTraversal(struct TreeNode* root, int* returnSize){
    int index=0,*val=NULL,size=0;
    struct TreeNode *p=NULL,*prev=NULL;

    struct TreeNode **TreeStack=calloc(sizeof(struct TreeNode*),101);

    if(root==NULL)
    {
        *returnSize=0;
        return NULL;
    }

    TreeStack[index++]=root;
    p=TreeStack[index-1];
    while(index!=0)
    {
        while(p)
        {
            p=p->left;
            if(p==NULL)break;
            TreeStack[index++]=p;
            
        }
        if(index==0)break;
        p=TreeStack[index-1];
        p=p->right;
        if(p!=NULL&&prev!=p)
        {
            TreeStack[index++]=p;
            continue;
        }else
        {
            size++;
            val=realloc(val,sizeof(int)*size);
            prev=TreeStack[index-1];
            val[size-1]=prev->val;
            index--;
            p=NULL;
        }
    }
    *returnSize=size;
    return val;
}

N叉树的前序遍历

思路:与二叉树类似,不同的是要从最右边的节点往左开始进栈。代码如下:
在这里插入图片描述

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     int numChildren;
 *     struct Node** children;
 * };
 */
/**********定义一个栈结构,实现进栈出栈的方法************/
typedef struct{
    struct Node **tree;
    int size;
    //int index;
}NodeStack;

NodeStack* NodeStackCreat(void)
{
    NodeStack *p;

    p=calloc(sizeof(NodeStack),1);
    //p->index=0;
    p->size=0;
    p->tree=NULL;
    return p;
}

int NodeStackPush(NodeStack *obj,struct Node *node)
{
    obj->size++;
    obj->tree=realloc(obj->tree,sizeof(struct Node*)*obj->size);
    if(obj->tree==NULL)return -1;
    obj->tree[obj->size-1]=node;
    return 0;
}

struct Node* NodeStackPop(NodeStack *obj)
{
    if(obj->size==0)
    {
        return NULL;
    }
    obj->size--;
    struct Node* p=obj->tree[obj->size];
    obj->tree=realloc(obj->tree,sizeof(struct Node*)*obj->size);
    return p;
}
bool NodeStackIsEmpty(NodeStack *obj)
{
    if(obj->size==0)return true;
    return false;
}
/**********定义一个栈结构,实现进栈出栈的方法************/
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* preorder(struct Node* root, int* returnSize) {
    int size=0,*val=NULL;
    struct Node *res;

    NodeStack *MyStack=NodeStackCreat();

    //根节点入栈
    NodeStackPush(MyStack, root);

    while(!NodeStackIsEmpty(MyStack))
    {
        res=NodeStackPop(MyStack);
        if(res==NULL)break;
        while(res)
        {
            size++;
            val=realloc(val,sizeof(int)*size);
            val[size-1]=res->val;
            //printf("%d,",res->val);
            if(res->numChildren>0)
            {
                for(int i=res->numChildren;i>0;i--)
                {
                    NodeStackPush(MyStack,res->children[i-1]);
                }
                break;
            }else break;
        }
        
        
    }
    *returnSize=size;
    return val;
}

N 叉树的后序遍历

在这里插入图片描述

思路:这里与二叉树的后序思路不同(因为想了好久也没想出来对应着二叉树的模板写),想了种取巧的方法,就是用前序求解,只不过是从左往右一次入栈。到最后输出结果时做一次反转,比如上图中从右往左看,从上往下看的顺序依次是:1,4,2,3,6,5;刚好是后序的反转。
代码如下:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     int numChildren;
 *     struct Node** children;
 * };
 */
typedef struct{
    struct Node **tree;
    int size;
    //int index;
}NodeStack;

NodeStack* NodeStackCreat(void)
{
    NodeStack *p;

    p=calloc(sizeof(NodeStack),1);
    //p->index=0;
    p->size=0;
    p->tree=NULL;
    return p;
}

int NodeStackPush(NodeStack *obj,struct Node *node)
{
    obj->size++;
    obj->tree=realloc(obj->tree,sizeof(struct Node*)*obj->size);
    if(obj->tree==NULL)return -1;
    obj->tree[obj->size-1]=node;
    return 0;
}

struct Node* NodeStackPop(NodeStack *obj)
{
    if(obj->size==0)
    {
        return NULL;
    }
    obj->size--;
    struct Node* p=obj->tree[obj->size];
    obj->tree=realloc(obj->tree,sizeof(struct Node*)*obj->size);
    return p;
}
bool NodeStackIsEmpty(NodeStack *obj)
{
    if(obj->size==0)return true;
    return false;
}
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* postorder(struct Node* root, int* returnSize) {
    int size=0,*val=NULL;
    struct Node *res;

    NodeStack *MyStack=NodeStackCreat();

    //根节点入栈
    NodeStackPush(MyStack, root);

    while(!NodeStackIsEmpty(MyStack))
    {
        res=NodeStackPop(MyStack);
        if(res==NULL)break;
        while(res)
        {
            size++;
            val=realloc(val,sizeof(int)*size);
            val[size-1]=res->val;
            //printf("%d,",res->val);
            if(res->numChildren>0)
            {
                for(int i=0;i<res->numChildren;i++)
                {
                    NodeStackPush(MyStack,res->children[i]);
                }
                break;
            }else break;
        }
    }
    for(int i=0,j=size-1;i<j;i++,j--)
    {
        int temp=val[i];
        val[i]=val[j];
        val[j]=temp;
    }
    *returnSize=size;
    return val;
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值