二分木の実装(データ構造+ C言語)

1.主な関数呼び出し

a。配列を使用してすべてのノードをバイナリツリーに格納し、それらをプレオーダートラバーサルメソッドに格納します(バイナリツリーは、以下で作成するときにプレオーダーメソッドで作成する必要があり、配列のストレージメソッドは作成時と同じ)空のノットポイントは#で表されます。main関数では、ルートノードを格納するためのポインタを定義するだけで済みます。ルートノードによると、二分木のすべてのノードにアクセスできます。

//主函数
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;
}

2.二分木を作成します

a。1つ目は、二分木の確立です。再帰的な方法を使用して二分木を作成します。

構造タイプ

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

プレオーダートラバーサルを使用してバイナリツリーを作成します

b。ここで3つのパラメーターを見てみましょう。最初のパラメーターはバイナリツリーのノードを格納する配列であり、2番目のパラメーターは配列の長さであり、3番目のパラメーターは配列が終了したかどうかを判断するために使用されます。通常の変数を使用して再帰的に入力する第1層にある場合、変更も判断もできないため、変数のアドレスを渡して配列が終了したかどうかを判断します。

//通过前序遍历创建二叉树
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;
}

3.二分木を破壊します

1. main関数でバイナリツリーを作成するときは、ポインタ変数を使用してルートノードを格納します。実際にはポインタを操作するため、バイナリツリーを破棄するときにポインタが指すスペースを解放するだけで済みます。関数内の変数であるため、そのアドレスを関数に渡す必要があります。したがって、ポインター変数のアドレスを関数に渡す必要があるため、ここでは第2レベルのポインターを使用します。

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

4.二分木でノードの数を見つけます

a。再帰を使用して、バイナリツリー内のノードの数を計算します。空のノードに移動すると、0が返されます。空のノードでない場合は、左側の子ノードの数と右側の子ノードの数が返されます。独自のノードを追加します。

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

5.二分木のリーフノードの数を見つけます

a。再帰的にバイナリツリーのリーフノードの数を計算します。空のノードに移動すると、0が返されます。空でないノードであり、その左右の子ノードが空の場合、 nodeはリーフノードであり、直接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);
}

6.二分木のk番目のレベルでノードの数を見つけます

a。再帰的方法を使用して、バイナリツリーのk番目の層のノード数を見つけます。したがって、パラメーターを渡すと、追加のパラメーターkがあり、空のノードに到達すると、0が返され、それを渡します。子ノードに移動するたびに、パラメータkが1つ減ると、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);
} 

7.二分木で値が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;
}

8.二分木の深さを見つけます

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;
}

9.二分木の注文前、注文後のトラバーサル

二分木(C言語)のプレオーダートラバーサル-プログラマーが求めた

二分木(C言語)の順序通りの走査-プログラマーが求めた

二分木(C言語)のポストオーダートラバーサル-プログラマーが求めた

10.二分木のレベル順トラバーサル

a。再帰的な方法を使用して、二分木のレベル順序をトラバースします。このアルゴリズムは、k番目のレベルの要素数を見つけるのと似ています。パラメーターを渡すときは、追加のパラメーターiを渡してレベル数を判断します。ノードの子ノードの各トラバースポイントがクリックされると、iが1減算されます。iが0の場合、レイヤーは対応するレイヤーにトラバースされ、直接印刷されます。したがって、最初に二分木の高さnを見つけます。次に、ループを使用して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");
}

11.二分木が完全な二分木であるかどうかを判断します

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