第4章第1节练习题7 交换二叉树所有节点左右子树

问题描述

试编写一算法,实现将二叉树中所有节点的左右子树进行交换

算法思想

因为需要实现将二叉树中所有节点的左右子树交换,因此最简单的方式便是使用递归的方式。而完成整个树左右子树的交换,可以考虑两种方式,从上向下依次交换,或从下往上依次交换。

从上向下:假如T为整棵树的根节点,则首先交换T的左右孩子,然后交换T的左孩子(注:此时T的左孩子为原来二叉树中T的右孩子)的左右孩子,依次类推,当T的左子树交换完成后,再接着交换T的右孩子(注:此处同理,T的右孩子为原来二叉树中T的左孩子)的左右孩子,依次类推完成整棵树的左右子树交换。

从下往上:首先交换整棵树中最左边的两个叶子节点,然后接着交换次左边的两个叶子节点,接着将最左边的两个叶子节点父节点与次左边的两个叶子节点的父节点进行交换,依次类推,直到交换到根节点为止。

为了保证结果的正确性,利用先序遍历和中序遍历可以唯一确定一个二叉树的特点,同时打印出先序遍历结果和中序遍历结果以保证结果可靠性。

算法描述

从上向下的交换的过程有点类似于先序遍历的过程,因此使用先序递归遍历的方式实现

void SwapLRtreePre(BiTNode* T){
    BiTNode* temp;
    if(T==NULL){
        return;
    }
    temp=T->lchild;
    T->lchild=T->rchild;
    T->rchild=temp;
    SwapLRtreePre(T->lchild);
    SwapLRtreePre(T->rchild);
}

从下往上的交换过程有点类似于后序遍历的过程,因此使用后序递归遍历的方式实现

void SwapLRtreePost(BiTNode* T){
    BiTNode* temp;
    if(T==NULL){
        return;
    }
    SwapLRtreePost(T->lchild);
    SwapLRtreePost(T->rchild);
    temp=T->lchild;
    T->lchild=T->rchild;
    T->rchild=temp;
}

附件

//AB#DG###CE##F##
#include<stdio.h>
#include<stdlib.h>

typedef char ElemType;
typedef struct BiTNode{
    ElemType data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

BiTNode* CreateBiTree(BiTNode*);
void SwapLRtreePre(BiTNode*);
void SwapLRtreePost(BiTNode*);
void PreOrder(BiTNode*);
void InOrder(BiTNode*);
void Jundge(BiTNode*);

//----------------------------------------------------------

int main(int argc, char* argv[]){
    BiTNode* T=(BiTNode*)malloc(sizeof(BiTNode));
    T=CreateBiTree(T);

    Jundge(T);
    SwapLRtreePre(T);
    Jundge(T);

    Jundge(T);
    SwapLRtreePost(T);
    Jundge(T);

    return 0;
}

BiTNode* CreateBiTree(BiTNode* T){
    ElemType x;
    scanf("%c",&x);
    if(x==‘#‘){
        return NULL;
    }
    T=(BiTNode*)malloc(sizeof(BiTNode));
    T->data=x;
    T->lchild=CreateBiTree(T->lchild);
    T->rchild=CreateBiTree(T->rchild);
    return T;
}

//----------------------------------------------------------

//以“先序遍历”的思想交换左右子树
void SwapLRtreePre(BiTNode* T){
    BiTNode* temp;
    if(T==NULL){
        return;
    }
    temp=T->lchild;
    T->lchild=T->rchild;
    T->rchild=temp;
    SwapLRtreePre(T->lchild);
    SwapLRtreePre(T->rchild);
}

//以“后序遍历”的思想交换左右子树
void SwapLRtreePost(BiTNode* T){
    BiTNode* temp;
    if(T==NULL){
        return;
    }
    SwapLRtreePost(T->lchild);
    SwapLRtreePost(T->rchild);
    temp=T->lchild;
    T->lchild=T->rchild;
    T->rchild=temp;
}

//----------------------------------------------------------

void Jundge(BiTNode* T){
    printf("---------------\n");
    PreOrder(T);
    printf("\n");
    InOrder(T);
    printf("\n");
}

void PreOrder(BiTNode* T){
    if(T==NULL){
        return;
    }
    printf("%c",T->data);
    PreOrder(T->lchild);
    PreOrder(T->rchild);
}

void InOrder(BiTNode* T){
    if(T==NULL){
        return;
    }
    InOrder(T->lchild);
    printf("%c",T->data);
    InOrder(T->rchild);
}
时间: 2024-10-14 06:06:10

第4章第1节练习题7 交换二叉树所有节点左右子树的相关文章

第4章第1节练习题12 删除以指定节点为根节点的所有子树

问题描述 已知二叉树以二叉链表存储,编写算法完成对于树中每一个元素值为x的节点,删去以它为根的子树,并释放相应空间 算法思想 本题可以分成两个部分来完成.第一步:查找值为x的节点:第二步:删除以值为x的节点为根节点的所有子树: 因为删除的是x的所有子树,因此遍历方式应该选择自上而下的遍历方式,即先序遍历或层次遍历方式,这里选择层次遍历的方式实现. 删除值为x的节点的所有子树,可以考虑使用递归的方式: 即此时可以认为删除的是以值为x的节点作为根节点的树: 首先删除该树的叶子节点,这样该树的倒数第二

第4章第1节练习题9 反向层次遍历算法

问题描述 试给出二叉树的自下而上,从右到左的层次遍历算法 算法思想 一般的二叉树层次遍历算法是自上向下,从左到右的遍历,这里的遍历顺序恰好相反,而运用栈先进后出的特点实现顺序的反转. 因此可以考虑在原来的层次遍历算法的基础上加上栈的基本操作.在出队的同时将各节点入栈,在所有的节点全部入栈后,依次出栈访问便可解决该问题. 算法描述 void InLevelOrder(BiTNode* T){ BiTNode *p=T; SqQueue Q; InitQueue(&Q); SqStack S; In

第4章第1节练习题6 二叉树叶子节点链接成单链表

问题描述 设计一个算法,将二叉树的叶子节点按从左到右的顺序连成一个单链表,表头指针为head.链接时用叶子节点的右指针来存放单链表指针. 算法思想 题目要求将叶子节点按自左向右的次序连接成一个单链表,因此很容易考虑到的便是将整棵二叉树按照先序或中序或后序的方式遍历一次. 在遍历的过程中对叶子节点单独判断,如果是叶子节点,则将其做一个标识(比如用额外的指针指向该节点),接着遍历下一个叶子节点,遍历到另一个叶子节点后,然后让已被标识的叶子节点的右孩子指向该节点,依次类推便可以实现将叶子节点连接成单链

第1章第2节练习题3 删除最小值结点

问题描写叙述 试编写在带头结点的单链表L中删除一个最小值结点的高效算法(如果最小值结点是唯一的) 算法思想 在链表中删除最小值的前提是必须找到最小值元素是哪个结点,因此设置指针p对全部结点进行遍历,使用指针min指向最小值结点.可是由于涉及到删除操作,明显在仅仅有指针min和指针p的条件下删除操作是极为不方便的. 若单纯的删除指针p指向的结点会造成断链.若採用2.5.2删除自身结点的方法,又会出现多次赋值操作. 因此直接引入两个分别指向其前驱结点的指针pre和premin,如此.删除操作过程会更

第1章第2节练习题4 删除指定区间结点

问题描述 设一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有其值在给定值s与t之间(包含s和t,要求s<t)的所有结点 算法思想 因为链表逻辑上无序,删除指定区间结点的前提是找到这些指定区间结点.因此从头节点开始对整个链表进行一次遍历,若找到满足题意的结点,删除即可. 算法描述 void Delts(LNode* head, ElemType t, ElemType s) { LNode *pre=head; LNode *p=head->next; while(

第4章第1节练习题10 判断某二叉树是否为完全二叉树

问题描述 试写一算法,完成判定某二叉树是否为完全二叉树的功能 算法思想 根据完全二叉树的定义,具有n个节点的完全二叉树与满二叉树中的编号从1~n的节点一一对应,可以考虑使用层次遍历的思想来实现. 将所有节点入队(包括空节点).当遇到空节点时,查看其后是否还有不为空的节点:如果没有,则为完全二叉树:如果有,则不是完全二叉树: 算法描述 int IsComplete(BiTNode* T){ SqQueue Q; InitQueue(&Q); BiTNode *p=T; EnQueue(&Q,

第2章第2节练习题3 使用队列模拟渡口管理

问题描写叙述 汽车轮渡口,过江渡船每次能载10辆车过江.过江车分为客车和货车类.上渡船有例如以下规定: 1).同类车先到先上船. 2).客车先于货车上渡船,其每上4辆客车,才同意放上一辆货车: 3).若等待客车不足4辆.则以货车取代: 4).若无货车等待,同意客车都上船. 试设计一个算法模拟渡口管理 算法思想 经过分析,发现此题实际上就是队列的基本操作,唯一的不同就是在入队的时候,对于顺序进行了限制. 使用队列Q表示每次载渡的车辆,队列Qp表示客车.Qt表示货车队列: 假设Qp中元素足够.则每从

第3章第1节练习题1 蛇形矩阵

问题描述 蛇形矩阵即使用二维数组完成来回曲折的赋值,举例说明如下所示的形式即为蛇形数组. 算法思想 观察该二维数组,只是可以"人为"的发现它就像一条蛇的形状来回爬行,然而并没有什么卵用,不能明确的站在计算机的角度上来实现这个数组.于是将所有的下标列出来便可以得到下述所述的曲线走势. 然后结合第一张图便可以发现 数字从2~3的过程中,下标行变化范围是0~1:下标列范围是1~0: 数字从4~6的过程中,下标行变化范围是2~0:下标列范围是0~2: 数字从7~10的过程中,下标行变化范围是0

第1章第2节练习题2 非递归删除指定结点

问题描写叙述 在带头结点的单链表L中.删除全部值为x的结点,并释放其空间,假设值为x的结点不唯一,试编写算法实现以上的操作 算法思想 使用指针p指向数据域为x的结点.使用指针pre指向指针p所指结点的前驱结点,从前向后进行遍历.假设指针p指向的结点的数据域为x,则删除.假设指针p指向的结点的数据域不为x,继续向后遍历就可以. 算法描写叙述 void DelNodeX(LNode *head, ElemType x) { LNode *pre=head; LNode *p=head->next;