1.二叉树的建立与输出
参考https://blog.csdn.net/m0_63137469/article/details/124612827
输入说明:按照先序遍历方式建立树,左/右孩子为空输入-1即可。建立完成后p->data表示根节点的值,根的左孩子的值用p->lchild->data表示
#include <stdio.h>
#include <malloc.h>
#include <iostream>
using namespace std;
typedef struct BiTNode {
int data;
struct BiTNode *lchild, *rchild;
}BiTNode, * BiTree;
BiTree creat_tree(void) {//建立
int data;
scanf_s("%d", &data);
BiTree p = (BiTree)malloc(sizeof(BiTNode));
BiTree prot = p;//第一个根节点的地址另外保存
p->data = data;
if (data == -1) {
return NULL;
}
else {
printf("请输入%d左子树(输入-1代表不用创建): ", data);
p->lchild = creat_tree();//新创建树,将地址赋值给根节点的左指针域
printf("请输入%d右子树(输入-1代表不用创建): ", data);
p->rchild = creat_tree();//新创建树,将地址赋值给根节点的右指针域
return prot;
}
}
int main() {
printf("请输入第一个节点的数据:");
BiTree p = creat_tree();//建立
cout << "根节点,根节点的左孩子,根节点的右孩子的值依次为";
cout << p->data<<" ";
cout << p->lchild->data<<" ";
cout << p->rchild->data;
return 0;
}
输出结果
2.二叉树建立后用层序完整输出
(1)以下为层序遍历只输出非空结点代码
#include <stdio.h>
#include <malloc.h>
#include <iostream>
using namespace std;
typedef struct BiTNode {
int data;
struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;
BiTree creat_tree(void) {//建立,直接复制
int data;
scanf_s("%d", &data);
BiTree p = (BiTree)malloc(sizeof(BiTNode));
BiTree prot = p;
p->data = data;
if (data == -1) {
return NULL;
}
else {
printf("请输入%d左子树(输入-1代表不用创建): ", data);
p->lchild = creat_tree();
printf("请输入%d右子树(输入-1代表不用创建): ", data);
p->rchild = creat_tree();
return prot;
}
}
typedef struct LinkNode {//队列基本操作相关
BiTree data;
struct LinkNode* next;
}LinkNode;
typedef struct {
LinkNode* front, * rear;
}LinkQueue;
void InitQueue(LinkQueue& Q) {//初始化
Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
Q.front->next = NULL;
}
void EnQueue(LinkQueue& Q, BiTree x) {
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
Q.rear->next = s;
Q.rear = s;
}
bool DeQueue(LinkQueue& Q, BiTree &x) {
if (Q.front == Q.rear)//判空
return false;
LinkNode* p = Q.front->next;
x = p->data;
Q.front->next = p->next;
if (Q.rear == p)
Q.rear = Q.front;
free(p);
return true;
}
void LeverOrder(BiTree T) {//【层序遍历输出】
LinkQueue Q;
InitQueue(Q);//初始化辅助队列
BiTree p;
EnQueue(Q, T);//根结点入队
while (Q.front!=Q.rear) {//队列不空则循环
DeQueue(Q, p);//队头结点出队
cout << p->data;
if (p->lchild != NULL)
EnQueue(Q, p->lchild);//左孩子入队
if (p->rchild != NULL)
EnQueue(Q, p->rchild);//右孩子入队
}
}
int main() {
printf("请输入第一个节点的数据:");
BiTree p = creat_tree();//建立二叉树
LeverOrder(p);//层序输出
return 0;
}
(2)以下为层序遍历以完全二叉树形式输出代码(空结点用0表示)
#include <stdio.h>
#include <malloc.h>
#include <iostream>
using namespace std;
typedef struct BiTNode {
int data;
struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;
BiTree creat_tree(void) {//建立,直接复制
int data;
scanf_s("%d", &data);
BiTree p = (BiTree)malloc(sizeof(BiTNode));
BiTree prot = p;
p->data = data;
if (data == -1) {
return NULL;
}
else {
printf("请输入%d左子树(输入-1代表不用创建): ", data);
p->lchild = creat_tree();
printf("请输入%d右子树(输入-1代表不用创建): ", data);
p->rchild = creat_tree();
return prot;
}
}
typedef struct LinkNode {//结点
BiTree data;
struct LinkNode* next;
}LinkNode;
#define MaxSize 100
typedef struct {//定义
BiTree data[MaxSize];//存放元素
int front, rear;//头尾指针
}SqQueue;
void InitQueue(SqQueue& Q) {//初始化
Q.rear = Q.front = 0;
}
bool IsEmpty(SqQueue Q) {//判空
if (Q.rear == Q.front)
return true;
}
int count2 = 0;//记录结点总数
int CountPreOrder(BiTree T) {//借用先序遍历统计结点个数
if (T != NULL)
{
count2++;
CountPreOrder(T->lchild);//访问左子树
CountPreOrder(T->rchild);//访问右子树
}
return count2;
}
void LeverOrder(BiTree T,int countsum) {//层序遍历输出部分
int temp=0;//计数
SqQueue Q;
InitQueue(Q);//初始化辅助队列
BiTree p;
int a[100];//辅助数组
int i = 0;
Q.data[Q.rear] = T;
Q.rear = Q.rear + 1;
while (Q.front!=Q.rear) {//队列不空则循环
p = Q.data[Q.front];
if (!p) {//用0表示的空结点放入数组
a[i] = 0;
i++;
temp++;//记录放入的空结点数量
}
else {
a[i] = p->data;//非空结点放入数组
i++;
}
if (i == temp + countsum)
break;
Q.front = Q.front + 1;
if (p && p->lchild != NULL) {
Q.data[Q.rear] = p->lchild;//左孩子入队
}
else {
Q.data[Q.rear] = NULL;
}
Q.rear = Q.rear + 1;
if (p && p->rchild != NULL) {
Q.data[Q.rear] = p->rchild;//右孩子入队
}
else {
Q.data[Q.rear] = NULL;
}
Q.rear = Q.rear + 1;
}
for (int j = 0; j < i; j++) {//输出数组
cout << a[j] << " ";
}
}
int main() {
printf("请输入第一个节点的数据:");
BiTree p = creat_tree();//建立二叉树
int count=CountPreOrder(p);
//swap(p);//新增代码
LeverOrder(p,count);
return 0;
}
效果如图
3.应用一
如:假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度
算法思想:采用层次遍历的算法,设置变量level记录当前结点所在的层数,设置变量last指向当前层的最右结点,每次层次遍历出队时与last指针比较,若两者相等,则层数加1,并让last指向下一层的最右结点,直到遍历完成。level的值即为二叉树的高度。
实现代码
#include <stdio.h>
#include <malloc.h>
#include <iostream>
using namespace std;
typedef struct BiTNode {
int data;
struct BiTNode *lchild, *rchild;
}BiTNode, * BiTree;
BiTree creat_tree(void) {//建立,直接复制
int data;
scanf_s("%d", &data);
BiTree p = (BiTree)malloc(sizeof(BiTNode));
BiTree prot = p;
p->data = data;
if (data == -1) {
return NULL;
}
else {
printf("请输入%d左子树(输入-1代表不用创建): ", data);
p->lchild = creat_tree();
printf("请输入%d右子树(输入-1代表不用创建): ", data);
p->rchild = creat_tree();
return prot;
}
}
#define MaxSize 100
int Btdepth(BiTree T) {//【本题算法】
if (!T)
return 0;
int front = -1, rear = -1;
int last = 0, level = 0;
BiTree Q[MaxSize];
Q[++rear] = T;
BiTree p;
while (front < rear) {
p = Q[++front];
if (p->lchild)
Q[++rear] = p->lchild;
if (p->rchild)
Q[++rear] = p->rchild;
if (front == last) {
level++;
last = rear;
}
}
return level;
}
int main() {
printf("请输入第一个节点的数据:");
BiTree p = creat_tree();//建立二叉树
int level=Btdepth(p);//新增代码
cout << "层数为:"<< level;
return 0;
}
结果
4.应用二
交换所有结点的左右子树
#include <stdio.h>
#include <malloc.h>
#include <iostream>
using namespace std;
typedef struct BiTNode {
int data;
struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;
BiTree creat_tree(void) {//建立,直接复制
int data;
scanf_s("%d", &data);
BiTree p = (BiTree)malloc(sizeof(BiTNode));
BiTree prot = p;
p->data = data;
if (data == -1) {
return NULL;
}
else {
printf("请输入%d左子树(输入-1代表不用创建): ", data);
p->lchild = creat_tree();
printf("请输入%d右子树(输入-1代表不用创建): ", data);
p->rchild = creat_tree();
return prot;
}
}
typedef struct LinkNode {//结点
BiTree data;
struct LinkNode* next;
}LinkNode;
#define MaxSize 100
typedef struct {//定义
BiTree data[MaxSize];//存放元素
int front, rear;//头尾指针
}SqQueue;
void InitQueue(SqQueue& Q) {//初始化
Q.rear = Q.front = 0;
}
bool IsEmpty(SqQueue Q) {//判空
if (Q.rear == Q.front)
return true;
}
int count2 = 0;
int CountPreOrder(BiTree T) {//借用先序遍历统计结点个数
if (T != NULL)
{
count2++;
CountPreOrder(T->lchild);//访问左子树
CountPreOrder(T->rchild);//访问右子树
}
return count2;
}
void LeverOrder(BiTree T,int countsum) {
int temp=0;//计数,看是否达到最后一个结点
SqQueue Q;
InitQueue(Q);//初始化辅助队列
BiTree p;
int a[100];//辅助数组
int i = 0;
Q.data[Q.rear] = T;
Q.rear = Q.rear + 1;
while (Q.front!=Q.rear) {//队列不空则循环
p = Q.data[Q.front];
if (!p) {
a[i] = 0;
i++;
temp++;
}
else {
a[i] = p->data;
i++;
}
if (i == temp + countsum)
break;
Q.front = Q.front + 1;
if (p && p->lchild != NULL) {
Q.data[Q.rear] = p->lchild;//左孩子入队
}
else {
Q.data[Q.rear] = NULL;
}
Q.rear = Q.rear + 1;
if (p && p->rchild != NULL) {
Q.data[Q.rear] = p->rchild;//右孩子入队
}
else {
Q.data[Q.rear] = NULL;
}
Q.rear = Q.rear + 1;
}
for (int j = 0; j < i; j++) {
cout << a[j] << " ";
}
}
void swap(BiTree& T) {//【本题算法】
if (T) {
swap(T->lchild);
swap(T->rchild);
BiTree temp;
temp = T->lchild;
T->lchild = T->rchild;
T->rchild = temp;
}
}
int main() {
printf("请输入第一个节点的数据:");
BiTree p = creat_tree();//建立二叉树
int count=CountPreOrder(p);
swap(p);//新增代码
LeverOrder(p,count);
return 0;
}
结果