提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
数据结构二叉树的常见遍历及其他常见操作。
1.头文件
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<assert.h>
//二叉树结构体
typedef struct treenode{
int data;
struct treenode *l, *r;
} TreeNode;
// 结点
typedef struct node{
TreeNode* data; //队列中元素类型为tree node
struct node *next;
} Node;
//队列
typedef struct queue{
int size;
Node * front, *rear; //队首结点(虚拟头结点) 队尾结点
} Queue;
//栈
typedef struct stack
{
int size;
Node * top, *head; //栈顶结点 虚拟头结点
} Stack;
//创建结点
Node *getNewNode(TreeNode* val);
//初始化栈
Stack* initStack();
//压栈
void pushStack(Stack *st, TreeNode *val);
//出栈
TreeNode* popStack(Stack *st);
//前序遍历(非递归实现)
void preorderTraversal(TreeNode * root);
//中序遍历(非递归实现)
void inorderTraversal(TreeNode * root);
//后序遍历(非递归实现)
void postorderTraversal(TreeNode * root);
//初始化队列
Queue* initQueue();
//元素入队
void pushQueue(Queue*que, TreeNode* node);
//元素出队
TreeNode* popQueue(Queue*que);
// 随机生成一颗二叉树
TreeNode* insertNodeToTree(TreeNode * root, int val);
//前序遍历(递归实现)
void preTraversal(TreeNode * root);
//中序遍历(递归实现)
void inTraversal(TreeNode * root);
//后序遍历(递归实现)
void postTraversal(TreeNode * root);
//层序遍历
void levelTraversal(TreeNode * root);
//获取树的高度
int getHeight(TreeNode * root);
//获取树中最大值
int getMaximum(TreeNode * root);
2.源代码
#include "binaryTree.h"
//创建结点
Node *getNewNode(TreeNode* val)
{
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = val;
newNode->next = NULL;
return newNode;
}
//初始化栈
Stack* initStack(){
Stack * st = (Stack*)malloc(sizeof(Stack));
TreeNode *tn = (TreeNode*)malloc(sizeof(TreeNode));
tn->data = 0;
st->head = getNewNode(tn);
st->top = st->head;
st->size = 0;
return st;
}
//压栈
void pushStack(Stack *st, TreeNode *val){
assert(st != NULL);
Node * newnode = getNewNode(val);
st->top->next = newnode;
st->top = newnode;
st->size++;
}
//出栈
TreeNode* popStack(Stack *st){
assert(st != NULL);
Node *p = st->head;
while (p->next != st->top)
{
p = p->next;
}
Node* tmp = st->top; //栈顶结点
TreeNode *tn = tmp->data; //得到结点的data,为树结点
st->top = p;
st->top->next = NULL;
st->size--;
free(tmp);
return tn;
}
//前序遍历(非递归实现)
void preorderTraversal(TreeNode * root){
assert(root != NULL);
Stack *st = initStack(); //初始化栈
pushStack(st, root); //根结点入栈
while (st->size != 0) //当栈元素不为空时继续操作
{
TreeNode * tmp = popStack(st);
printf("%d ", tmp->data);
if(tmp->r) pushStack(st, tmp->r); //先进右子树 (栈为后进先出,先进后出)
if(tmp->l) pushStack(st, tmp->l); //后进左子树 根左右
}
}
//中序遍历(非递归实现)
void inorderTraversal(TreeNode * root){
assert(root != NULL);
Stack *st = initStack(); //初始化栈
TreeNode *p = root;
while (st->size != 0 || p) //当栈元素不为空或者当前结点存在时
{
if(p){ //一直往左找到最左边的结点
pushStack(st, p);
p = p->l;
}else{ //最左边的结点不存在则出栈当前元素,找右子树
p = popStack(st);
printf("%d ", p->data);
p = p->r;
}
}
}
//后序遍历(非递归实现)
//只用对前序遍历的 左右子树 进行交换 变为 根进根出,左进右进右出左出(根右左) 反转得到左右根(直接使用栈进行反转)
void postorderTraversal(TreeNode * root){
assert(root != NULL);
Stack *st = initStack(); //初始化栈
Stack *result = initStack(); //用来存储结果
pushStack(st, root);
while (st->size != 0) //当栈元素不为空时继续操作
{
TreeNode * tmp = popStack(st);
pushStack(result, tmp);
if(tmp->l) pushStack(st, tmp->l);
if(tmp->r) pushStack(st, tmp->r);
}
for(int i = result->size; i > 0; i--){ //遍历栈 一次输出结果
printf("%d ", popStack(result)->data);
}
}
//初始化队列
Queue* initQueue(){
Queue *que = (Queue*)malloc(sizeof(Queue));
TreeNode *tn = (TreeNode*)malloc(sizeof(TreeNode));
tn->data = 0;
que->front = que->rear = getNewNode(tn); //随机初始化一个值作为头尾结点 虚拟头
que->size = 0;
return que;
}
//元素入队
void pushQueue(Queue*que, TreeNode* node){
assert(que != NULL);
assert(node != NULL);
Node *newnode = getNewNode(node); //新建一个结点
que->rear->next = newnode; //在尾结点后面追加新结点
que->size++; //尺寸+1
que->rear = newnode; // 新加的结点变成了尾结点
}
//元素出队
TreeNode* popQueue(Queue*que){
assert(que != NULL);
// if(que->size == 0){
// return;
// }
Node *tmp = que->front->next; //让临时变量 保存真实第一个结点
TreeNode * tn = tmp->data;
que->front->next = tmp->next;
if(tmp == que->rear){ //当队列只有一个元素时,让队尾重新回到队首
que->rear = que->front;
}
que->size--;
free(tmp);
return tn;
}
// 随机生成一颗二叉树
TreeNode* insertNodeToTree(TreeNode * root, int val){ //传入根结点 还有要插入的数值
TreeNode * tn = (TreeNode *)malloc(sizeof(TreeNode)); //新建一个新结点
tn->data = val;
tn->l = NULL;
tn->r = NULL;
if(root == NULL){ //如果根结点为空 则把要插入的值放在根结点
root = tn;
}else{
TreeNode *tmp = root; //根结点不为空 开始向下寻找 定义临时结点变量
while (tmp != NULL)
{
if(val < tmp->data){ //如果要插入的值小于当前结点的值 放在左子树
if(tmp->l == NULL){ //左子树为空 直接挂新结点 结束
tmp -> l = tn;
return root;
}else{ //左子树不为空 把当前结点作为要遍历的结点继续向下寻找
tmp = tmp->l;
}
}else{ //如果要插入的值大于当前结点的值 放在右子树
if(tmp->r == NULL){ //右子树为空 直接挂新结点 结束
tmp -> r = tn;
return root;
}else{ //右子树不为空 把当前结点作为要遍历的结点继续向下寻找
tmp = tmp->r;
}
}
}
}
return root;
}
//前序遍历(递归实现)
void preTraversal(TreeNode * root){
if(root == NULL) return;
printf("%d ", root->data); //根
preTraversal(root->l) ; //左
preTraversal(root->r) ; //右
}
//中序遍历(递归实现)
void inTraversal(TreeNode * root){
if(root == NULL) return;
inTraversal(root->l) ; //左
printf("%d ", root->data); //根
inTraversal(root->r) ; //右
}
//后序遍历(递归实现)
void postTraversal(TreeNode * root){
if(root == NULL) return;
postTraversal(root->l) ; //左
postTraversal(root->r) ; //右
printf("%d ", root->data); //根
}
//层序遍历
void levelTraversal(TreeNode * root){
assert(root != NULL);
Queue*que = initQueue();
pushQueue(que, root); //根结点入队
while (que->size > 0){
TreeNode* tn = popQueue(que); //获取出队树结点的值
printf("%d ", tn->data); //打印出队结点值
if(tn->l)pushQueue(que, tn->l); //如果当前结点有左子树,左子树入队
if(tn->r)pushQueue(que, tn->r); //如果当前结点有右子树,右子树入队
}
}
//获取树的高度
int getHeight(TreeNode * root){
if(root == NULL) return 0;
else{
int left_height = getHeight(root->l); //得到左子树的高度
int right_height = getHeight(root->r); //得到右子树的高度
int max = left_height;
if(right_height > left_height){ //比较
max = right_height;
}
return max + 1; //+1 为根结点值
}
}
//获取树中最大值
int getMaximum(TreeNode * root){
if(root == NULL) return -1;
else{
int m1 = getMaximum(root->l); //返回左子树的值
int m2 = getMaximum(root->r); //返回右子树的值
int m3 = root->data; //当前结点的值
int max = m1; //初始最大值为左子树的值
if(max < m2) max = m2; //右子树大更新最大值为右子树值
if(max < m3) max = m3; //当前结点值大继续更新
return max;
}
}
int main(){
system("chcp 65001"); /* cmd chcp 命令切换字符编码为 utf-8 以显示中文 */
srand(time(NULL)); //设置随机种子 确保每次生成的数字是随机的
int n, num[105] = {0}; //局部变量中必须手动初始化数组 不初始化会有脏数据
TreeNode * root = (TreeNode*)malloc(sizeof(TreeNode)); //初始化一棵树
root = NULL;
scanf("%d", &n);
for(int i = 0; i < n; i++){
int x = rand() % 50;
while (num[x] != 0) //确保每次生成的数字不重复
{
x = rand() % 50;
}
num[x] = 1;
root = insertNodeToTree(root, x);
}
printf("前序遍历(递归) :");
preTraversal(root);
printf("\n中序遍历(递归) :");
inTraversal(root);
printf("\n后序遍历(递归) :");
postTraversal(root);
printf("\n前序遍历(非递归):");
preorderTraversal(root);
printf("\n中序遍历(非递归):");
inorderTraversal(root);
printf("\n后序遍历(非递归):");
postorderTraversal(root);
printf("\n层序遍历:");
levelTraversal(root);
int height = getHeight(root);
printf("\n树高为: %d", height);
int maxnum = getMaximum(root);
printf("\n最大值为: %d", maxnum);
return 0;
}
3.提示
转载请注明出处