HIT-哈工大数据结构-作业3(C++)

文章详细介绍了如何使用C++实现二叉树的动态链表存储结构,包括先序、中序、后序和层次遍历的递归与非递归算法。同时,提供了判断二叉树是否为完全二叉树的算法以及计算二叉树宽度的方法。通过示例代码展示了具体实现,并给出了实验结果。
摘要由CSDN通过智能技术生成

文件说明

文件名二叉树.cppMytree.hMyStack.hMyQueue.h
包含内容测试代码及遍历算法实现二叉树节点结构及遍历算法声明自建栈类自建队列类

1.编写建立二叉树的动态(或者静态)二叉链表存储结构(左右链表示)的程序,并以适当的形式显示和保存二叉树;

二叉树遍历所用到的MyStack栈类:

const int maxlength = 1000;


class MyStack {
public:
	MyStack();
	void MakeNull();//将栈置空
	void Push(BTREE a);//进栈
	BTREE Pop();//出栈
	bool Empty();//判断栈是否为空
	BTREE Top();

public:
	BTREE stk[maxlength];//用于存放横坐标、纵坐标
	int top;//用于记录栈顶
};

二叉树遍历所用到的MyQueue栈类:

const int Max = 1000;

class Queue {//尾进头出
public:    
    Queue();//无参构造初始化队列
    bool Empty();
    void EnQueue( BTREE x);
    BTREE DeQueue( );

public:
    int front;
    int rear;
    BTREE d[Max];
};

二叉树的遍历算法声明:

typedef struct node* BTREE;
struct node {
    BTREE lchild;
    BTREE rchild;
    char data;
};

void CreatBT(BTREE& T);//按先序序列建立二叉树的左右链存储结构
void PrintBT(BTREE T);//打印二叉树
void Re_PreOrder(BTREE T);//递归实现先序遍历
void Re_InOrder(BTREE T);//递归实现中序遍历
void Re_PostOrder(BTREE T);//递归实现后序遍历
void PreOrder(BTREE T);//先序遍历
void InOrder(BTREE T);//中序遍历
void PostOrder(BTREE T);//后序遍历
void LevelOrder(BTREE T);//层次遍历
void Visit(BTREE T);//访问节点
bool CheckTree(BTREE T);//判断是否为完全二叉树
int TreeWide(BTREE T);//递归计算二叉树宽度

动态二叉链表结构二叉树的保存和展示:

void CreatBTre(BTREE& T) {//按先序序列建立二叉树的左右链存储结构,#代表节点为空
    char ch;
    cin >> ch;

    if (ch == '#')T = NULL;
    else {
        T = new node;
        T->data = ch;
        CreatBTre(T->lchild);
        CreatBTre(T->rchild);
    }
}

void PrintBT(BTREE T) {//用两种遍历方式唯一地确定一棵树
    cout << "这是你所构造的唯一二叉树" << endl;
    cout << "其先序序列为";
    PreOrder(T);
    cout << endl << "其中序序列为";
    InOrder(T);
    cout << endl;
}

**2.采用二叉树的上述二叉链表存储结构,编写程序实现二叉树的先序、中序和 后序遍历的递归和非递归算法以及层序遍历算法,并以适当的形式显示和保存二叉树及其相应的遍历序列; **

void Re_PreOrder(BTREE T) {//递归先序遍历函数
    if (T != NULL) {
        Visit(T);//根
        Re_PreOrder(T->lchild);//左
        Re_PreOrder(T->rchild);//右
    }
}

void Re_InOrder(BTREE T) {//递归中序遍历函数
    if (T != NULL) {
        Re_InOrder(T->lchild);//左
        Visit(T);//根
        Re_InOrder(T->rchild);//右
    }
}

void Re_PostOrder(BTREE T) {//递归后序遍历函数
    if (T != NULL) {
        Re_PostOrder(T->lchild);//左
        Re_PostOrder(T->rchild);//右
        Visit(T);//根
    }
}

void PreOrder(BTREE T) {//先序遍历
    BTREE p = T;
    MyStack S;//建栈
    while (p || !S.Empty()) {//节点非空或栈不为空
        if (p) {//访问节点不为空
            Visit(p);//访问根
            S.Push(p);//进栈
            p = p->lchild;//访问左
        }
        else {//到底了,碰到空节点
            p = S.Pop();//取出栈顶不为空的节点
            p = p->rchild;//访问右
        }
    }
}

void InOrder(BTREE T) {//中序遍历
    BTREE p = T;
    MyStack S;//建栈
    while (p || !S.Empty()) {//节点非空或栈不为空
        if (p) {//访问节点不为空
            S.Push(p);//进栈
            p = p->lchild;//访问左
        }
        else {//到底了,碰到空节点
            p = S.Pop();//取出栈顶不为空的节点
            Visit(p);//可以理解为他的左孩子已经访问完了,再访问他自己
            p = p->rchild;//访问右
        }
    }
}

void PostOrder(BTREE T) {//后序遍历
    MyStack S;//建栈
    BTREE p = T;
    BTREE tag = NULL;//用来保存刚访问过的节点,作用是判断是否刚从右边返回
    while (p || !S.Empty()) {//节点非空或栈不为空
        if (p) {//访问节点不为空
            S.Push(p);//进栈
            p = p->lchild;//访问左
        }
        else {//到底了,碰到空节点
            p = S.Top();//访问栈顶元素
            if (p->rchild && p->rchild != tag)//右边有孩子且不等于标记
                p = p->rchild;//访问右
            else {//到达后序遍历待访问的第一个节点
                p = S.Pop();取出栈顶不为空的节点
                Visit(p);//访问自己
                tag = p;//标记成自己
                p = NULL;
            }
        }
    }
}

void LevelOrder(BTREE T) {//层序遍历
    Queue Q;//建立队列
    BTREE p;
    Q.EnQueue(T);//进队
    while (!Q.Empty()) {//队列不为空时
        p=Q.DeQueue();//取出队首
        Visit(p);//访问队首,由于队列是先进先出,访问顺序就跟入队顺序一样,相当于一层层访问
        if (p->lchild)//左不为空
            Q.EnQueue(p->lchild);//左进队
        if (p->rchild)//右不为空
            Q.EnQueue(p->rchild);//右进队
    }
}

**3.设计并实现判断任意一棵二叉树是否为完全二叉树的算法。 **

bool CheckTree(BTREE T) {//判断完全二叉树
    Queue Q;//建立队列
    if (T == NULL)//空树
        return true;
    Q.EnQueue(T);//进队
    BTREE p;
    while (!Q.Empty()) {//队列不为空时
        p = Q.DeQueue();//取出队首
        if (p->lchild && p->rchild) {//左右都有孩子,分别进队,也是一层一层进队的
            Q.EnQueue(p->lchild);
            Q.EnQueue(p->rchild);
        }
        else if (p->rchild && !p->lchild)//有右孩子没左孩子,不是完全二叉树,返回
            return false;
        else {//这一步理应达到完全二叉树的叶子节点或着上一层最右端节点
            if (p->lchild && !p->rchild)//有左孩子没右孩子,是上一层最右端节点
                Q.EnQueue(p->lchild);//进队
            while (!Q.Empty()) {//队列不为空时
                p = Q.DeQueue();//取出队首,在这之后应该全为叶子节点了
                if (p->lchild || p->rchild)
                    return false;
            }
        }
    }
    return true;
}

4.设计并实现计算任意一棵二叉树的宽度的(递归或非递归)算法。二叉树的 宽度是指其各层结点数的最大值。

int c[100];//这个是用来保存每一层的节点数的,从0层开始。全局变量默认值为0
int M = 0;//用来保存最大节点数
void layer_count(BTREE T, int k)//自顶向下递归找出最大宽度
{
    if (T == NULL)  return;
    c[k]++;
    if (M < c[k])
        M = c[k];
    layer_count(T->lchild, k + 1);
    layer_count(T->rchild, k + 1);
}

int TreeWide(BTREE T) {
    layer_count(T, 0);
    return M;
}

5.测试代码及实验结果

测试代码:

int main() {
    BTREE T;
    cout << "请用先序序列创建你的二叉树,#代表节点为空" << endl;
    CreatBTre(T);
    cout << "构造成功" << endl;
    PrintBT(T);
    cout << "以递归方式先序遍历二叉树" << endl;
    Re_PreOrder(T);
    cout << endl;
    cout << "先序遍历二叉树" << endl;
    PreOrder(T);
    cout << endl;
    cout << "以递归方式中序遍历二叉树" << endl;
    Re_InOrder(T);
    cout << endl;
    cout << "中序遍历二叉树" << endl;
    InOrder(T);
    cout << endl;
    cout << "以递归方式后序遍历二叉树" << endl;
    Re_PostOrder(T);
    cout << endl;
    cout << "后序遍历二叉树" << endl;
    PostOrder(T);
    cout << endl;
    cout << "层序遍历二叉树" << endl;
    LevelOrder(T);
    cout << endl;
    cout << endl;
    if (CheckTree(T))
        cout << "该树是完全二叉树" << endl;
    else
        cout << "该树不是完全二叉树" << endl;
    cout << "该树的宽度为:" << TreeWide(T) << endl;
    return 0;
}

实验结果:

树1:ABDH##I##EJ##K##CF#M##G##

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWKkcLq3-1677332114698)(2022120067-刘虹志-作业3.assets/1.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UJw6wOfR-1677332114698)(2022120067-刘虹志-作业3.assets/3.png)]

树2:ABDH##I##EJ##K##CFL###G##

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iB80i88U-1677332114699)(2022120067-刘虹志-作业3.assets/2.png)]

cout << “该树不是完全二叉树” << endl;
cout << “该树的宽度为:” << TreeWide(T) << endl;
return 0;
}




实验结果:

树1:ABDH##I##EJ##K##CF#M##G##



[外链图片转存中...(img-AWKkcLq3-1677332114698)]



[外链图片转存中...(img-UJw6wOfR-1677332114698)]

树2:ABDH##I##EJ##K##CFL###G##

[外链图片转存中...(img-iB80i88U-1677332114699)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ReUEk7mE-1677332114699)(2022120067-刘虹志-作业3.assets/4.png)]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值