二叉树(2.二叉树的遍历和实现)
Posted 水澹澹兮生烟.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树(2.二叉树的遍历和实现)相关的知识,希望对你有一定的参考价值。
二叉树(2)
2.5二叉树的遍历
什么是遍历?按照某种特性规则,对二叉树中的结点进行某种相应的操作,并且每个结点只操作一次。
2.5.1前序遍历
又称先根遍历,访问根结点的操作发生在遍历其左右子树之前。
//前序遍历
void preorder(node* root){
if(root){
printf("%d" ,root->data);
preorder(root->left);
preorder(root->right);
}
}
2.5.2中序遍历
又称中根遍历,访问根结点的操作发生在遍历其左右子树之间。
//中序遍历
void midorder(node* root){
if(root){
midorder(root->left);
printf("%d",root->data);
midorder(root->right);
}
}
2.5.3后序遍历
又称后根遍历,访问根结点的操作发生在遍历其左右子树之后。
postorder(node* root){
if(root)
{
postorder(root->left);
postorder(root->right);
printf("%d" ,root->data);
}
}
2.5.4层序遍历
堆二叉树的每一层进行遍历。
1.定义一个队列的结构并初始化,然后将根结点入队列
2.只要队列不空,循环进行以下操作:
从队列中取一个结点,遍历该结点,如果该节点测左孩子存在,将其入队列,若该结点的右孩子存在,入队列。然后将队头元素删掉。
3.删除队列
(队列实现的代码)
此时我们在这里需要的函数:
void QueueInit(queue* q);
//获取队头元素
DType QueueQhead(queue* q);
//出队列(将结点的孩子节点入队列)
void Queuepop(queue* q);
//入队列(将父结点出队列)
void Queuepush(queue* q, DType data);
//判空
int Queueempty(queue* q);
//销毁队列
void Queuedestroy(queue* q);
实现层序遍历:
leveOrder(node* root){
if(NULL==root) return;
//先定义一个队列
queue* q;
//初始化队列,将根节点入队列
QueueInit(&q);
Queuepush(&q,root);
while(!Queueempty(&q)){
//队列不空,先得到队头元素
node* p=QueueQhead(&q);
//打印队头元素
printf("%d",p->data);
//然后判断结点是否存在左右孩子,并将其入队列
if(p->left){
//作孩子入队列
Queuepush(&q,p->left);
}
if(p->right){
Queuepush(&q,p->right);
}
//然后出队列
ququepop(&q);
}
//再将队列进行销毁
void Queuedestroy(&q);
}
2.6二叉树的中的方法
2.6.1.二叉树的销毁
以遍历的思想堆二叉树进行销毁,此时我们采用后序遍历来进行销毁,如果采用前序遍历或者中序遍历,我们会再销毁孩子节点之前将父结点销毁掉,这样会再成数据丢失。
void destoryBinary(node** root){
//再进行销毁时,我们在最后一部要对root进行修改,因此我们在传参时要传二级指针
if(*root){
//在不为空的情况下进行销毁
destoryBinary(&(*root)->left);
destoryBinary(&(*root)->right);
free(*root);
*root=NULL;
}
}
2.6.2.二叉树的结点
再求的二叉树的结点的时候,我们首先要知道二叉树的他有空树和非空树。
当它为空树时,直接结点个数返回0;当它为非空时,他的结点个数为根结点+左子树节点个数+右子树结点个数。
//求二叉树中的结点
int getrootBinary(node* root){
if(NULL==root) return 0;
return 1+getrootBinary(root->left)+getrootBinary(root->right);
}
2.6.3.求二叉树的叶子结点
//求二叉树中的叶子结点
int getleaftroot(node* root){
if(NULL==root) return 0;
if(root->left==NULL&&root->right==NULL){
return 1;
}
return getleaftroot(root->left)+getleaftroot(root->right);
}
2.6.4.求二叉树的第k层的结点数
在这里我们需要考虑三点:
1.当树为空或者k=0时,直接返回0;
2.当树不为空且k=1时,返回1;
3.排除以上两种情况,我们求他的第k层元素个数直接去求是不好得出的,因此我们可以在其root的左右子树上求的k-1层即可,最后将其求得的个数+1。
int getbinarytreek(node* root,int k){
if(root==NULL||k==0) return 0;
if(k==1) return 1;
return getbinarytreek(root->left,k-1)+getbinarytreek(root->right,k-1);
}
2.6.5求树的高度
在这个中我们可以考虑求出他的左子树高度,并且求出他的右子树高度,然后比较左右子树的高度,选取大的值+1就是二叉树的高度。
//计算二叉树的高度
int getbinarytreehight(node* root){
if(NULL==root){
return 0;
}
int lefthight=getbinarytreehight(root->left);
int righthight=getbinarytreehight(root->right);
int hight=lefthight>righthight?lefthight+1:righthight+1;
return hight;
}
2.6.6查找二叉树中x结点
和前面的原理相似,利用遍历查找。
node* binaryTreeFind(node* root,int x){
node* cur=NULL;
if(root==NULL) return NULL;
if(root->data==x){
return root;
}
if(cur=binaryTreeFind(root->left,x))
return cur;
if(cur=binaryTreeFind(root->right,x))
return cur;
}
2.6.7二叉树的创建
创建二叉树时提供的序列中只包含了有效元素,如果遇到那个结点没有左孩子或者右孩子,是无法区分的,我们在序列中必须标记那些父结点有孩子,那些没有孩子,因此我们借助顺序表来进行标记。
//构建二叉树
BTnode* _creatBTree(int array[], int size, int* index, int invalid){
BTnode* root = NULL;
//index以值的方式进行传递当他在递归过程中修改之后,不会将修改会的值传到上一层中,因此我们此时要传地址
if (*index < size&&array[*index] != invalid){
root = getBTnode(array[*index]);
//此时,先对index进行++,
(*index)++;
root->left=_creatBTree(array, size, index, invalid);
(*index)++;
root->right=_creatBTree(array, size, index, invalid);
return root;
}
else{
return NULL;
}
}
BTnode* creatBTree(int* array, int size, int invalid){
int index = 0;
return _creatBTree(array, size, &index, invalid);
}
(附所有代码及运行结果):
BinaryTree.h
#pragma once
#include<stdio.h>
typedef int DType;
typedef struct BTnode{
//孩子表示法,分别是左孩子,右孩子
struct BTnode* left;
struct BTnode* right;
DType data;
}BTnode;
BTnode* getBTnode(DType data);
BTnode* _creatBTree(int* array, int size, int* index, int invalid);
BTnode* creatBTree(int* array, int size,int invalid);
void preorder(BTnode* root);
void midorder(BTnode* root);
void postorder(BTnode* root);
//二叉树的销毁
void destoryBinary(BTnode** root);
//求二叉树的结点
int getBinaryroot(BTnode* root);
//求二叉树的叶子结点个数
int getleafroot(BTnode* root);
//求二叉树第k层的结点数
int getbinarytreek(BTnode* root, int k);
//求树的高度
int getvinarytreehight(BTnode* root);
//查找二叉树中的x结点,如果找到返回其地址,若未找到返回0
BTnode* binaryTreefind(BTnode* root, DType x);
binaryTree.c
#include"BinaryTree.h"
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
//构建结点
BTnode* getBTnode(DType data){
struct BTnode* node = (struct BTnode*)malloc(sizeof(BTnode));
if (node == NULL){
assert(0);
return NULL;
}
node->data = data;
node->left = node->right = NULL;
return node;
}
//构建二叉树
BTnode* _creatBTree(DType array[], int size, int* index, DType invalid){
BTnode* root = NULL;
//index以值的方式进行传递当他在递归过程中修改之后,不会将修改会的值传到上一层中,因此我们此时要传地址
if (*index < size&&array[*index] != invalid){
root = getBTnode(array[*index]);
//此时,先对index进行++,
(*index)++;
root->left=_creatBTree(array, size, index, invalid);
(*index)++;
root->right=_creatBTree(array, size, index, invalid);
return root;
}
else{
return NULL;
}
}
BTnode* creatBTree(DType array[] , int size, DType invalid){
int index = 0;
return _creatBTree(array, size, &index, invalid);
}
void preorder(BTnode* root){
if (root == NULL){
return;
}
//先输出根结点
printf("%d\\t", root->data);
//递归遍历左子树
preorder(root->left);
//递归遍历右子树
preorder(root->right);
}
void midorder(BTnode* root){
if (root == NULL) return;
//递归遍历左子树
midorder(root->left);
//输出根结点
printf("%d\\t", root->data);
//递归遍历右子树
midorder(root->right);
}
void postorder(BTnode* root){
if (root == NULL) return;
//递归遍历左子树
postorder(root->left);
//递归遍历右子树
postorder(root->right);
//输出根结点
printf("%d\\t", root->data);
}
void destoryBinary(BTnode** root){
if (*root == NULL) return;
//在不为空的的情况下进行销毁
destoryBinary(&(*root)->left);
destoryBinary(&(*root)->right);
free(*root);
*root = NULL;
}
int getBinaryroot(BTnode* root){
if (root == NULL) return 0;
return 1 + getBinaryroot(root->left) + getBinaryroot(root->right);
}
int getleafroot(BTnode* root){
if (root == NULL) return 0;
if (root->left == NULL&&root->right == NULL){
return 1;
}
return getleafroot(root->left) + getleafroot(root->right);
}
int getbinarytreek(BTnode* root, int k){
if (root == NULL || k == 0) return 0;
if (k == 1) return 1;
return getbinarytreek(root->left, k - 1) + getbinarytreek(root->right, k - 1);
}
int getbinarytreehight(BTnode* root){
if (root == NULL) return 0;
//得到左子树的高度
int lefthight = getbinarytreehight(root->left);
int righthight = getbinarytreehight(root->right);
int hight = lefthight > righthight ? lefthight + 1 : righthight + 1;
return hight;
}
BTnode* binaryTreefind(BTnode* root, DType x){
BTnode* cur = NULL;
if (root == NULL) return NULL;
if (root->data == x) return root;
if (cur = binaryTreefind(root->left, x)){
//如果在左子树中找到,返回
return cur;
}
if (cur = binaryTreefind(root->right, x)){
//在右子树中找打,返回
return cur;
}
}
test.c
#include<stdio.h>
#include"binaryTree.h"
int main(){
int array[] = { 1, 2, 3, -1, -1, -1, 4, 5 ,-1,-1,6};
int size = sizeof(array) / sizeof(array[0]);
BTnode* root = creatBTree(array, size, -1);
printf("先序遍历:");
preorder(root);
printf("\\n中序遍历:");
midorder数据结构 二叉树的简单理解和代码实现