C語言二叉樹
本二叉樹的功能為:創建二叉樹,遞歸先根,中根,後根遍歷,二叉樹節點總數目,二叉樹深度,二叉樹葉子節點數,復制二叉樹,尋找某節點是否存在並輸出,交換左右子樹,插入某節點。
下面介紹每種算法的主要思路:
1.創建二叉樹:首先引入申請空間的指針節點。設葉子節點的左右子樹均為零,每當遇到輸入的數字為零時,將指針賦值為NULL,否則依次創建左右子樹。
2.遞歸遍歷:如根節點不為空,則依次訪問其左右子樹。
3.二叉樹節點總數:根節點為空返回零,否則返回1+左右子樹節點總數。
4.二叉樹深度:根節點為空返回零,否則返回1+左右子樹中深的那棵樹的深度。
5.二叉樹葉子節點總數:遞歸有兩個出口,若根節點為空,返回零;若根節點的左右子樹均為空,返回1。否則返回左右子樹之和。
6.復制二叉樹:類似創建二叉樹。
7.尋找節點是否存在:重點!
Node*Find(Node*root,int item){
Node*p=NULL; //需要引入一個空指針
if(root==NULL) return NULL;
if(root->data==item) {
return root;
}
p=Find(root->Left,item); //用指針p來儲存左子樹的尋找結果
if(p!=NULL) return p; //若p不為空,說明在左子樹中找到該節點,返回該節點
return Find(root->Right,item); //否則返回右子樹的尋找結果(無論是該節點指針或者NULL,最終將會有一個被返回)
}
(1)錯誤示範:警示!
Node*Find(Node*root,int item){
if(root==NULL) return NULL;
if(root->data==item) {
return root;
}
return Find(root->Left,item);
return Find(root->Right,item);
}
錯誤原因:該算法最終由於第一個return的存在,最終只能返回左子樹左面的那部分。
(2)錯誤示範:警示!
Node*Find(Node*root,int item){
if(root==NULL) return NULL;
if(root->data==item) {
return root;
}
Find(root->Left,item);
Find(root->Right,item);
}
錯誤原因:因為沒有return導致遞歸不能正常進行。
8.交換左右子樹:左右子樹只要有一個不為空就交換其左右子樹,若左子樹不為空,交換左子樹;若右子樹不為空,交換右子樹。
9.插入節點:利用Find函數找到相應節點並返回其指針,進行插入。
Node*Addition(Node*root,int item){ //截取插入函數的一部分
Node*r=root;
Node*p=NULL;
Node*q=NULL;
q = (Node*)malloc(sizeof(Node));
q->data=item;
q->Left=p->Left;
p->Left=q; //重點!p->Left=q而不是q=p->Left
q->Right=NULL;
}
以下是完整代碼:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct BinaryTreeNode
{
int data;
struct BinaryTreeNode *Left;
struct BinaryTreeNode *Right;
}Node;
//創建二叉樹,順序依次為中間節點->左子樹->右子樹
Node* createBinaryTree()
{
Node *p;
int ch;
cin>>ch;
if(ch == 0) //如果到了葉子節點,接下來的左、右子樹分別賦值為0
{
p = NULL;
}
else
{
p = (Node*)malloc(sizeof(Node));
p->data = ch;
p->Left = createBinaryTree(); //遞歸創建左子樹
p->Right = createBinaryTree(); //遞歸創建右子樹
}
return p;
}
//先序遍歷
void preOrderTraverse(Node* root)
{
if( root )
{
cout<<root->data<<‘ ‘;
preOrderTraverse(root->Left);
preOrderTraverse(root->Right);
}
}
//中序遍歷
void inOrderTraverse(Node* root)
{
if( root )
{
inOrderTraverse(root->Left);
cout<<root->data<<‘ ‘;
inOrderTraverse(root->Right);
}
}
//後序遍歷
void lastOrderTraverse(Node* root)
{
if( root )
{
lastOrderTraverse(root->Left);
lastOrderTraverse(root->Right);
cout<<root->data<<‘ ‘;
}
}
//二叉樹節點總數目
int Nodenum(Node* root)
{
if(root == NULL)
{
return 0;
}
else
{
return 1+Nodenum(root->Left)+Nodenum(root->Right);
}
}
//二叉樹的深度
int DepthOfTree(Node* root)
{
if(root)
{
return DepthOfTree(root->Left)>DepthOfTree(root->Right)?DepthOfTree(root->Left)+1:DepthOfTree(root->Right)+1;
}
if( root == NULL )
{
return 0;
}
}
//二叉樹葉子節點數
int Leafnum(Node* root)
{
if(!root)
{
return 0;
}
else if( (root->Left == NULL) && (root->Right == NULL) )
{
return 1;
}
else
{
return (Leafnum(root->Left) + Leafnum(root->Right)) ;
}
}
//復制二叉樹
Node*Copy(Node*copy){
Node*p;
if(copy==NULL) p=NULL;
else{
p=(Node*)malloc(sizeof(Node));
p->data=copy->data;
p->Left=Copy(copy->Left);
p->Right=Copy(copy->Right);
return p;
}
}
//尋找節點
Node*Find(Node*root,int item){
Node*p=NULL;
if(root==NULL) return NULL;
if(root->data==item) {
return root;
}
p=Find(root->Left,item);
if(p!=NULL) return p;
return Find(root->Right,item);
}
//輸出是否存在該節點
void Output(Node*root){
if(root!=NULL) cout<<"Find it";
else cout<<"No find";
}
//交換左右子樹
Node*Exchange(Node*root){
if(root->Left!=NULL||root->Right!=NULL){
Node*temp=root->Left;
root->Left=root->Right;
root->Right=temp;
}
if(root->Left) Exchange(root->Left);
if(root->Right) Exchange(root->Right);
return root;
}
//插入某節點
Node*Addition(Node*root,int item){
int location;
Node*r=root;
Node*p=NULL;
Node*q=NULL;
if(root==NULL) return NULL;
if(item==0){
cout<<"無法插入該節點";
return root;
}
cout<<"請輸入要插入節點的位置";
cin>>location;
p=Find(r,location);
if(p==NULL){
cout<<"不存在該節點要插入的位置";
cout<<endl;
return root;
}
q = (Node*)malloc(sizeof(Node));
q->data=item;
q->Left=p->Left;
p->Left=q;
q->Right=NULL;
return root;
}
//主函數
int main()
{
int number=2;
int number1=9;
Node *addition=NULL;
Node *output=NULL;
Node *exchange=NULL;
Node *root = NULL;
Node *example=NULL;
Node *example_addition=NULL;
Node *example_exchange=NULL;
root = createBinaryTree();
example=Copy(root);
example_addition=Copy(root);
example_exchange=Copy(root);
addition=Addition(example_addition,number1);
exchange=Exchange(example_exchange);
printf("二叉樹建立成功");
cout<<endl;
cout<<"二叉樹總節點數為:"<<Nodenum(root)<<endl;
cout<<"二叉樹深度為:"<<DepthOfTree(root)<<endl;
cout<<"二叉樹葉子節點數為:"<<Leafnum(root)<<endl;
cout<<"前序遍歷結果:"<<endl;
preOrderTraverse(root);
cout<<endl;
cout<<"中序遍歷結果:"<<endl;
inOrderTraverse(root);
cout<<endl;
cout<<"後序遍歷結果:"<<endl;
lastOrderTraverse(root);
cout<<endl;
cout<<"添加後前序遍歷結果:"<<endl;
preOrderTraverse(addition);
cout<<endl;
cout<<"添加後中序遍歷結果:"<<endl;
inOrderTraverse(addition);
cout<<endl;
cout<<"添加後後序遍歷結果:"<<endl;
lastOrderTraverse(addition);
cout<<endl;
cout<<"復制二叉樹前序遍歷結果:"<<endl;
preOrderTraverse(example);
cout<<endl;
cout<<"復制二叉樹中序遍歷結果:"<<endl;
inOrderTraverse(example);
cout<<endl;
cout<<"復制二叉樹後序遍歷結果:"<<endl;
lastOrderTraverse(example);
cout<<endl;
cout<<"交換後二叉樹前序遍歷結果:"<<endl;
preOrderTraverse(exchange);
cout<<endl;
cout<<"交換後二叉樹中序遍歷結果:"<<endl;
inOrderTraverse(exchange);
cout<<endl;
cout<<"交換後二叉樹後序遍歷結果:"<<endl;
lastOrderTraverse(exchange);
cout<<endl;
output=Find(root,number);
Output(output);
return 0;
}
C語言二叉樹