二叉树的实现(数据结构+C语言)

一.主函数调用

a.我们使用数组存储二叉树中的所有结点,以前序遍历的方式存储(下面创建的时候就必须采用前序的方式创建二叉树,在数组中的存储方式必须和创建时的方式相同)空结点以#表示.在主函数中我们只需定义一个指针用来存储根节点就行,根据根节点我们便可以访问到二叉树中的所有结点.

//主函数
int main(){
  BTDataType str[]="ABD##E#H##CF##G##";
  int num=0;
  int k=0;
  char x,Empty;
  BTNode* root;
  root=CreateBinaryTree(str,strlen(str),&num);
  printf("层序遍历为:");
  BinaryTreeLevelOrder(root);
  printf("结点个数为:%d\n",BinaryTreeSize(root));
  printf("叶子结点个数为:%d\n",BinaryTreeLeafSize(root));
  printf("请输入k=");
  scanf("%d",&k);
  printf("第%d层节点的个数为:%d\n",k,BinaryTreeLevelKSize(root,k));
  Empty=getchar();
  printf("请输入x=");
  scanf("%c",&x);
  printf("以%c为根的树中总共有%d个节点\n",x,BinaryTreeSize(BinaryTreeFind(root,x)));
  printf("二叉树的深度为:%d\n",BinaryTreeDepth(root));
  printf("%d\n",BinaryTreeComplete(root));
  BinaryTreeDestory(&root);
  return 0;
}

二.创建二叉树

a.首先是二叉树的建立我们采用的递归的方式进行二叉树的创建.

结构体类型:

typedef struct BinaryTreeNode{
  BTDataType _data;//数据域
  struct BinaryTreeNode* _left;//存储左孩子
  struct BinaryTreeNode* _right;//存储右孩子
}BTNode;

采用前序遍历创建二叉树:

b.我们这里来看看三个参数,第一个参数为存储二叉树节点的数组,第二个参数为数组的长度,第三个参数用来判断数组是否走完,使用普通变量在递归进入下一层的时候无法改变不能进行判断,因此我们将变量的地址传进来进行判断数组是否走完.

//通过前序遍历创建二叉树
BTNode* CreateBinaryTree(BTDataType* str,int n,int* pi){
  if('#' == str[*pi]){//判出条件
    return NULL;
  }
  if(*pi < n){//判断数组是否走完
    BTNode* cur=(BTNode*)malloc(sizeof(BTNode));//为节点申请空间
    cur->_data=str[*pi];//赋值
    cur->_left=NULL;
    cur->_right=NULL;
    (*pi)++;
    if(*pi < n){
      cur->_left=CreateBinaryTree(str,n,pi);//创建左孩子
    }
    (*pi)++;
    if(*pi < n){
      cur->_right=CreateBinaryTree(str,n,pi);//创建右孩子
    } 
    return cur;
  }
  return NULL;
}

三.销毁二叉树

1.我们在主函数中创建二叉树时是用指针变量来存储根节点的,因此在销毁二叉树时只需要将该指针指向的空间释放即可,因为我们在函数中对指针变量进行实际操作,所以需要将其地址传入函数,因此需要将指针变量的地址传入函数,因此这里使用二级指针.

//二叉树的销毁
void BinaryTreeDestory(BTNode** root){
  if(NULL==*root){
    return;
  }
  free(*root);
  *root=NULL;
}

四.求二叉树的节点个数

a.使用递归的方式对二叉树的节点个数进行计算,遍历走到空节点时返回0,如果不是空节点就返回自己的左孩子结点的个数加上自己的右孩子结点的个数加上自己的结点.

扫描二维码关注公众号,回复: 13829262 查看本文章
//二叉树的结点个数
int BinaryTreeSize(BTNode* root){
  if(NULL==root){
    return 0;
  }
  return BinaryTreeSize(root->_left)+BinaryTreeSize(root->_right)+1;
}

五.求二叉树的叶子结点的个数

a.使用递归的方式对二叉树的叶子结点个数进行计算,遍历时走到空节点则返回0,如果是非空节点并且其左右孩子节点都为空则证明该节点为叶子结点直接返回1,如果是非空节点但是不是叶子结点则返回其左子树的叶子结点个数加上其右子树的叶子结点个数.

//二叉树叶子结点个数
int BinaryTreeLeafSize(BTNode* root){
  if(NULL==root){
    return 0;
  }
  if(NULL==root->_left && NULL==root->_right){
    return 1;
  }
  return BinaryTreeLeafSize(root->_left)+BinaryTreeLeafSize(root->_right);
}

六.求二叉树第k层节点的个数

a.使用递归的方式求二叉树的第k层节点的个数,因此我们传参的时候多了一个参数k,当走到空节点时返回0,我们每次遍历到其孩子结点的时候传参时k都减一,当检测到k为0时说明遍历到了第k层,此时该节点如果不为空则直接返回1,如果该节点既不为空也不是第k层的话直接返回该节点的左子树中第k层结点的个数加上该节点右子树中第k层节点的个数.

//二叉树第k层结点的个数
int BinaryTreeLevelKSize(BTNode* root,int k){
  if(NULL==root){
    return 0;
  }
  if(0==k){
    return 1;
  }
  return BinaryTreeLevelKSize(root->_left,k-1)+BinaryTreeLevelKSize(root->_right,k-1);
} 

七.在二叉树中查找值为x的结点

a.使用递归的方式查找值为x的结点,遍历的空节点时直接返回空,如果不是空节点则判断该节点的值是否为x如果为x则直接返回该节点,(因此该算法是采用前序的方式进行遍历的,所以只能找到第一个值为x的结点),如果该节点既不是空节点又不是值为x的结点则直接返回其左右子树中非空的结点.

//二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root,BTDataType x){
  if(NULL==root){
    return NULL;
  }
  if(x==root->_data){
    return root;
  }
  BTNode* first=BinaryTreeFind(root->_left,x);
  BTNode* second=BinaryTreeFind(root->_right,x);
  if(NULL==first){
    return second; 
  }
  return first;
}

八.求二叉树的深度

a.使用递归的方式计算二叉树的深度,当遍历到空节点时返回0,如果该节点不是空节点则返回其左子树和右子树中更大的一个加上自己本身的层数.

//求二叉树的深度
int BinaryTreeDepth(BTNode* root){
  if(NULL==root){
    return 0;
  }
  int Dep_1=BinaryTreeDepth(root->_left);
  int Dep_2=BinaryTreeDepth(root->_right);
  if(Dep_1>Dep_2){
    return Dep_1+1;
  }
  return Dep_2+1;
}

九.二叉树的前中后序遍历

二叉树的前序遍历(C语言)_guo5411的博客-CSDN博客_c语言前序遍历

二叉树的中序遍历(C语言)_guo5411的博客-CSDN博客_c语言二叉树中序遍历算法

二叉树的后序遍历(C语言)_guo5411的博客-CSDN博客

十.二叉树的层序遍历

a.我们采用递归的方式进行二叉树的层序遍历,该算法类似于求第k层的元素个数,我们传参的时候多传一个参数i用来判断层数,每遍历一个节点的孩子结点时i减一,当i为0时层遍历到相应层次直接打印即可,因此我们先求出二叉树的高度n然后使用循环将i从0开始到n进行传参调用第一个函数,将每层的数据打印即可.

//二叉树的层序遍历
void BinaryTreeLevelOrder_1(BTNode* root,int i){
  if(NULL==root){
    return;
  }
  if(0==i){
    printf("%c",root->_data);
    return;
  }
  BinaryTreeLevelOrder_1(root->_left,i-1);
  BinaryTreeLevelOrder_1(root->_right,i-1);
}

void BinaryTreeLevelOrder(BTNode* root){
  if(NULL==root){
    return;
  }
  int Dep_=BinaryTreeDepth(root);
  int i;
  for(i=0;i<Dep_;i++){
    BinaryTreeLevelOrder_1(root,i);
  }
  printf("\n");
}

十一.判断二叉树是否为完全二叉树

a.采用层序遍历的方式对二叉树中的结点进行存储,遇到空节点直接存储为#,存储完之后对数组进行遍历计算个数,遇到#时停止,此时计算出的个数与二叉树的结点个数相同则该二叉树为完全二叉树返回1(我们应该知道完全二叉树采用层序遍历时遍历到最后一个节点前是不会遇到空节点的,如果遇到则该树不是完全二叉树),如果不同则该二叉树不是完全二叉树返回0.

//判断二叉树是否是完全二叉树
void BinaryTreeComplete_1(BTNode* root,int i,BTDataType* arry,int* num){
  if(NULL==root){
    arry[(*num)++]='#';
    return;
  }
  if(0==i){
    arry[(*num)++]=root->_data;
    return;
  }
  BinaryTreeComplete_1(root->_left,i-1,arry,num);
  BinaryTreeComplete_1(root->_right,i-1,arry,num);
}

int BinaryTreeComplete(BTNode* root){
  if(NULL==root){
    printf("该节点为空!\n");
    return -1;
  }
  BTDataType* arry=(BTDataType*)malloc(sizeof(BTDataType)*2*BinaryTreeSize(root));
  if(NULL==arry){
    printf("申请失败!\n");
    return -1;
  }
  int i=0;
  int count=0;
  int num=0;
  for(i=0;i<BinaryTreeDepth(root);i++){
    BinaryTreeComplete_1(root,i,arry,&num);
  }
  while(arry[count] != '#'){
    count++;
  }
  if(BinaryTreeSize(root)==count){
    return 1;
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_49312527/article/details/122901882