代码随想录算法训练营第十三天(2)|二叉树非递归遍历(迭代法)、二叉树层序遍历、144 前序遍历、145 后序遍历、94 中序遍历(前中后遍历的两种写法)、102 二叉树的层序遍历

 ​​​​​​

一、 144 前序遍历

 //前序遍历:中左右
 //递归法
 void PreOrder(struct TreeNode* root,int*ret,int *returnSize)
 {
    if(root==NULL)
        return;
    else{
        ret[(*returnSize)++]=root->val;//中
        PreOrder(root->left,ret,returnSize);//左
        PreOrder(root->right,ret,returnSize);//右
    }
 }
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int *ret = (int*)malloc(sizeof(int)*101);
    *returnSize = 0;
    PreOrder(root,ret,returnSize);
    return ret;
}
//迭代法
//入栈顺序:中右左
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int *ret = (int*)malloc(sizeof(int)*101);
    *returnSize = 0;
    if(root==NULL)
        return NULL;
    struct TreeNode*stack[100];//用数组模拟栈操作
    int top = -1;//栈顶指针
    stack[++top]=root;//根节点入栈
    while(top>=0){
        struct TreeNode* p = stack[top--];  //弹出栈顶节点
        ret[(*returnSize)++] = p->val;//记录节点值
        if(p->right!=NULL)
            stack[++top] = p->right;//右入栈
        if(p->left!=NULL)
            stack[++top] = p->left;//左入栈
    }
    return ret;
}

二、145 后序遍历

//后序遍历:左右中
//递归法
void PreOrder(struct TreeNode* root,int *ret, int* returnSize){
    if(root==NULL)
        return;
    else{
        PreOrder(root->left,ret,returnSize);//左
        PreOrder(root->right,ret,returnSize);//右
        ret[(*returnSize)++] = root->val;//中
    }
}
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    int *ret = (int*)malloc(sizeof(int)*101);
    *returnSize = 0;
    PreOrder(root,ret,returnSize);
    return ret;
}

//迭代法
int* postorderTraversal(struct TreeNode* root, int* returnSize){
    int *ret = (int*)malloc(sizeof(int)*101);
    *returnSize = 0;
    struct TreeNode*stack[100];
    int top = -1;
    struct TreeNode*lastvisited = NULL;//用于记录上一个访问过的节点
    struct TreeNode*p= root;
    while(p!=NULL||top!=-1){
        if(p!=NULL){
            stack[++top]=p;
            p=p->left;
        }
        else{
            struct TreeNode*peekNode = stack[top];//查看栈顶节点
            //若栈顶节点的右子结点存在且从未被访问过
            if(peekNode->right!=NULL&&peekNode->right!=lastvisited){
                p = peekNode->right;
            }
            else{
                ret[(*returnSize)++] = peekNode->val;//输出栈顶元素值
                lastvisited = peekNode;//标记已被访问,防止重复访问
                top--;//出栈
            }
        }
    }
    return ret;
}

三、94 中序遍历

//中序遍历:左中右
//递归法
void PreOrder(struct TreeNode* root,int *ret, int* returnSize){
    if(root==NULL)
        return;
    else{
        PreOrder(root->left,ret,returnSize);//左
        ret[(*returnSize)++]=root->val;//中
        PreOrder(root->right,ret,returnSize);//右
    }
}
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    int*ret=(int*)malloc(sizeof(int)*101);
    *returnSize = 0;
    PreOrder(root,ret,returnSize);
    return ret;
}

//迭代法
int* inorderTraversal(struct TreeNode* root, int* returnSize){
    int*ret=(int*)malloc(sizeof(int)*101);
    *returnSize = 0;
    if(root==NULL)
        return NULL;
    struct TreeNode*stack[101];//创建数组模拟栈操作
    int top = -1;//栈顶指针
    struct TreeNode*p=root;//从栈顶开始遍历
    while(p!=NULL||top>=0){
        if(p!=NULL){
            stack[++top] = p;//保存节点值
            p=p->left;//一直向左遍历
        }
        else{
            p=stack[top--];//出栈
            ret[(*returnSize)++]=p->val;//访问根节点
            p=p->right;
        }
    }
    return ret;
}

四、102 二叉树的层序遍历

int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    if(root==NULL){//若根节点为空
        *returnSize = 0;
        *returnColumnSizes = NULL;
        return NULL;
    }
    *returnSize = 0;//先将保存层的数组置0
    int**arr=(int **)malloc(sizeof(int*)*2001);//创建一个二维二叉树数组
    int i=0;//层下标
    *returnColumnSizes = (int*)malloc(sizeof(int)*2001);//创建一个层数组
    struct TreeNode *queue[2001];//创建一个队列数组模拟队列操作
    int front = 0;//队头,出队
    int rear = 0;//队尾,入队
    struct TreeNode*cur;//定义一个指针用于遍历二叉树
    queue[rear++]=root;//根入队
    while(front!=rear){//队不为空
        int last = rear;//保存这一层最后一个数据的下标,因为在处理当前层节点时,rear 的值会随着新节点的入队而改变,所以用 last记录当前层最后一个元素的位置,以便后续确定当前层的元素个数。
        int j=0;//这一层元素的下标
        arr[i]=(int *)malloc(sizeof(int)*(last-front));//为第i层开辟内存空间,last-front就是第i层的元素个数
        (*returnColumnSizes)[i]=last-front;//用于存储每一层的元素个数
        while(front<last){//这里是<不是<=,因为队列的尾指针指向的是最后一的元素的下一个节点,这个节点为空,当front=last时代表已经遍历结束
            cur = queue[front++];//从队列中弹出一个元素,并移动头指针
            arr[i][j++] = cur->val;//将cur的值放到二维数组 arr 的第 i 行的第 j 个位置,然后j向后移动,指向下一个要要存储的元素位置
            if(cur->left!=NULL){//左孩子不为空,则入队
                queue[rear++]=cur->left;
            }
            if(cur->right!=NULL){//右孩子不为空,则入队
                queue[rear++]=cur->right;
            }
        }
        i++;//处理下一层
    }
    *returnSize = i;
    return arr;//arr通过*returnColumnSizes获取每一层的元素个数,通过*returSizes获取总层数
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值