PTA 03-树2 List Leaves

这篇博客介绍了如何解决PTA(Programming Task Assistant)平台上的一道题目,该题目要求按从上到下、从左到右的顺序列出二叉树的所有叶子节点。博主首先使用静态链表存储二叉树结构,然后通过层次遍历(广度优先搜索)的方法来实现题目要求的功能。代码中展示了如何构建二叉树以及层次遍历的实现细节,包括使用队列进行节点的入队和出队。最后,博主分享了层次遍历的相关知识,包括队列操作的常用函数和层次遍历的基本步骤。

03-树2 List Leaves

原题网址

这是我第一次做PTA不用借鉴网络上的代码并且AC的题目!!

Given a tree, you are supposed to list all the leaves in the order of top down, and left to right.

Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree – and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a “-” will be put at the position. Any pair of children are separated by a space.

Output Specification:
For each test case, print in one line all the leaves’ indices in the order of top down, and left to right. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.

Sample Input:
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
Sample Output:
4 1 5

思路

1.首先还是用静态链表存储二叉树

struct TreeNode{
    int data;
    int left,right;
};
TreeNode T[MaxTree];

并用全局数组T[]用来存储
2.由于题目要求由上到下由左到右输出–联想到层次遍历
3.整体框架先建立起来:

int main(){
    int root=BuildTree(T);
    FloorPrint(root);
    return 0;
}

代码

#include<iostream>
#include<queue>
#define MaxTree 10
#define null -1
using namespace std;
struct TreeNode{
    int data;
    int left,right;
};
TreeNode T[MaxTree];
int BuildTree(TreeNode T[]){//建立二叉树
    int N;
    scanf("%d",&N);
    int check[N],root=-1;
    for(int i=0;i<N;i++)
        check[i]=0;
    for(int i=0;i<N;i++){
        T[i].data=i;//data记录结点号
        char lc,rc;
        scanf("\n%c %c",&lc,&rc);
        if(lc!='-'){
            T[i].left=lc-'0';
            check[T[i].left]=1;
        }else{
            T[i].left=null;
        }
        if(rc!='-'){
            T[i].right=rc-'0';
            check[T[i].right]=1;
        }else{
            T[i].right=null;
        }
    }
    for(int i=0;i<N;i++){
        if(check[i]==0){
            root=i;
            break;
        }
    }
    return root;
}

void FloorPrint(int root){//层次遍历输出
    queue<TreeNode> q;
    if(root!=-1){//树不为空
        q.push(T[root]);
    }
    int flag=0;//判断是否第一个输出
    while(q.empty()==false){
        TreeNode temp=q.front();
        if(temp.left==null&&temp.right==null){//是叶子结点
            if(flag){
                printf(" ");
            }
            flag=1;
            printf("%d",temp.data);
        }
        if(temp.left!=null){//左结点不空
            TreeNode templeft=T[temp.left];
            q.push(templeft);
        }
        if(temp.right!=null){//左结点不空
            TreeNode tempright=T[temp.right];
            q.push(tempright);
        }
        q.pop();
    }
}

int main(){
    int root=BuildTree(T);
    FloorPrint(root);
    return 0;
}

相关知识的回顾

层次遍历

转自博客链接

void FloorPrint_QUEUE(pTreeNode &Tree) //层序遍历_队列实现
{
    queue < pTreeNode> q;
    if (Tree != NULL)
    {
        q.push(Tree);   //根节点进队列
    }

    while (q.empty() == false)  //队列不为空判断
    {
        cout << q.front()->data << " → "; 

        if (q.front()->leftPtr != NULL)   //如果有左孩子,leftChild入队列
        {
            q.push(q.front()->leftPtr);   
        }

        if (q.front()->rightPtr != NULL)   //如果有右孩子,rightChild入队列
        {
            q.push(q.front()->rightPtr);
        }
        q.pop();  //已经遍历过的节点出队列
    }
}

队列

在这里插入图片描述
queue 和 stack 有一些成员函数相似,但在一些情况下,工作方式有些不同:

  • front():返回 queue 中第一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue
    为空,返回值是未定义的。
  • back():返回 queue 中最后一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue
    为空,返回值是未定义的。
  • push(const T& obj):在 queue 的尾部添加一个元素的副本。这是通过调用底层容器的成员函数 push_back()
    来完成的。
  • push(T&& obj):以移动的方式在 queue 的尾部添加元素。这是通过调用底层容器的具有右值引用参数的成员函数
    push_back() 来完成的。
  • pop():删除 queue 中的第一个元素。
  • size():返回 queue 中元素的个数。
  • empty():如果 queue 中没有元素的话,返回 true。
  • emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。
  • swap(queue &other_q):将当前 queue 中的元素和参数 queue
    中的元素交换。它们需要包含相同类型的元素。也可以调用全局函数模板 swap() 来完成同样的操作。

注意:queue没有.top()函数只有.front()函数,不要和stack搞混!

### PTA 7-2 二叉搜索结构实现与问题解决方案 #### 描述 在处理PTA平台上有关二叉搜索(BST)的问题时,理解其基本操作至关重要。这不仅涉及创建和维护一棵平衡的二叉搜索,还包括执行诸如插入、删除以及查询等常见任务。 #### 创建二叉搜索 为了构建一个有效的二叉搜索,在初始化阶段应当首先定义好节点的数据结构,并确保每次新增元素都能按照左子小于父节点而右子大于等于父节点的原则正确放置[^3]。 ```cpp struct TreeNode { int val; TreeNode *left, *right; TreeNode(int x) : val(x), left(NULL), right(NULL){} }; ``` 当向已存在的二叉搜索中添加新值时,可以通过递归方式来完成: ```cpp TreeNode* insertIntoBST(TreeNode* root, int val){ if (!root) return new TreeNode(val); if (val < root->val) root->left = insertIntoBST(root->left, val); else root->right = insertIntoBST(root->right, val); return root; } ``` #### 删除特定数值对应的节点 对于删除操作而言,存在三种可能的情形:目标节点无任何孩子;只有一个孩子;有两个孩子。前两种情形相对容易处理——只需调整指针指向即可解决问题。然而第三种情况则较为复杂一些,通常的做法是从右侧寻找最小值作为替代品并移除之[^4]。 ```cpp TreeNode* deleteNode(TreeNode* root, int key){ if(!root) return nullptr; if(key < root->val) root->left = deleteNode(root->left, key); else if(key > root->val) root->right = deleteNode(root->right, key); else{ // Node with only one child or no child if(!root->left || !root->right){ TreeNode* temp = root->left ? root->left : root->right; if(temp == NULL){ // No children case temp = root; root = NULL; }else{ // One child case *root = *temp; } free(temp); }else { // Two children cases TreeNode* minNodeOnRightSubtree = findMin(root->right); root->val = minNodeOnRightSubtree->val; root->right = deleteNode(root->right,minNodeOnRightSubtree->val); } } return root; } // Helper function to find minimum value node in a given tree. TreeNode* findMin(TreeNode* node){ while(node && node->left != NULL) node = node->left; return node; } ``` #### 查询功能 除了上述增删改之外,另一个重要的方面就是如何高效地定位某个具体的键值位置或是判断两个指定节点之间的关系,比如求解它们之间最近共同祖先等问题[^2]。 ```cpp bool searchInBST(TreeNode* root,int target){ if(!root) return false; if(target<root->val) return searchInBST(root->left,target); else if(target>root->val) return searchInBST(root->right,target); else return true; } ``` 通过以上方法论可以较好地应对大部分基础性的二叉搜索编程挑战。当然实际应用过程中还可能会遇到更多复杂的场景需求进一步优化算法效率或增强鲁棒性等方面的工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值