普通的二叉树也可以完成比较多的,可以解决很多我们现实生活中的问题,比如在图书管理系统等系统中我们都可以用到树的结构和思维来实现。
一、二叉树的定义
二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都比较简单,因此二叉树显得特别重要。二叉树特点是每一个节点最多只能有两颗子树,且有左右之分。
二叉树包括了
节点:二叉树的基本组成部分。有值,没有左右之分。
左子树:指向左子节点的二叉树,如果没有左子树,则为空。
右子树:指向右子节点的二叉树,如果没有右子树,则为空。
根:二叉树的根节点,如果为空,则为二叉树。
二、二叉数的具体代码
二叉树的实现首先要定义一个结构体,结构体里面要包含节点数据的值,指向左右孩子的指针。代码如下:
typedef struct BinaryTreeNode {
int data; //节点的数据
struct BinaryTreeNode* left; //指向左孩子的指针
struct BinaryTreeNode* right; //指向右孩子的指针
}Binary;
创建一个二叉树节点代码:
Binary* newBinaryTreeNode(int data) {
Binary* node = (Binary*)malloc(sizeof(Binary));
node->data = data; //给节点的值赋值
node->left = NULL; //左孩子为空
node->right = NULL; //右孩子为空
return node; //返回该节点
}
插入一个二叉树节点:
Binary* insertNode(Binary* root, int data) {
if (root == NULL) {
return newBinaryTreeNode(data);//如果是空树就新建一个节点
}
if (data < root->data) { //小于父节点的节点接在左子树
root->left = insertNode(root->left, data);
} else if (data > root->data) { //大于父节点的节点接在右子树
root->right = insertNode(root->right, data);
}
return root;
}
先序遍历二叉树:
void preorderTraversal(Binary* root) //根左右
{
if (root == NULL) {
return;
}
printf("%d ", root->data);
preorderTraversal(root->left);
preorderTraversal(root->right);
}
中序遍历二叉树:
void inorderTraversal(struct BinaryTreeNode* root) //左根右
{
if (root == NULL) {
return;
}
inorderTraversal(root->left);
printf("%d ", root->data);
inorderTraversal(root->right);
}
后序遍历二叉树:
void postorderTraversal(struct BinaryTreeNode* root) //左右根
{ if(root == NULL) {
return;
}
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%d ", root->data);
}
删除节点代码:
Binary* delete_node(Binary* root,int data){
if(root==NULL){
return root;
}
//查找指定数据的节点和它的父节点
Binary *node=NULL,*parent=NULL,*temp=root;
while(temp!=NULL){
if(data==temp->data){
node=temp;
break;
}
//当前节点为父节点,向其子节点查找
parent=temp;
if(data<temp->data){
temp=temp->left;
}
else temp=temp->right;
//可能查找不到指定数据的节点
if(node==NULL){
return node;
}
//检查当前待删节点是否符合条件
if(node->left==NULL||node->right==NULL){
Binary *subnode=NULL;
if(node->left==NULL){
//待删节点左子树为空,用右子树替代
subnode=node->right;
}
else{
//待删节点右子树为空,用左子树替代
subnode=node->left;
}
}
if(parent!=NULL){
if(parent->left==node)
parent->left=subnode;
else
parent->right=subnode;
}
else{
//删除树的根节点
root=subnode;
}
return root;
}
//左右子树都存在,按中序遍历查找该节点替代节点
Binary *replacer=node,replacerparent=parent;
//查找直接前驱
temp=node->left;
while(temp!=NULL){
replacerparent=replacer;
replacer=temp;
temp=node->right;
}
//删除节点
replacerparent=replacer->data;
if(parent!=NULL){
if(parent->left==node){
parent->left=replacer;
}
else
parent->right=replacer;
}
replacer->left=node->left;
replacer->right=node->right;
node->left=NULL;
node->right=NULL;
}
以上是我学到的二叉树基本操作。
三、完整代码
#include <stdio.h> #include <stdlib.h> // 二叉树的节点结构体 typedef struct BinaryTreeNode { int data; struct BinaryTreeNode* left; struct BinaryTreeNode* right; }Binary; // 创建一个新的二叉树节点 Binary* newBinaryTreeNode(int data) { Binary* node = (Binary*)malloc(sizeof(Binary)); node->data = data; //给节点的值赋值 node->left = NULL; //左孩子为空 node->right = NULL; //右孩子为空 return node; //返回该节点 } // 插入一个节点到二叉树中 Binary* insertNode(Binary* root, int data) { if (root == NULL) { return newBinaryTreeNode(data);//如果是空树就新建一个节点 } if (data < root->data) { //小于父节点的节点接在左子树 root->left = insertNode(root->left, data); } else if (data > root->data) { //大于父节点的节点接在右子树 root->right = insertNode(root->right, data); } return root; } // 先序遍历二叉树 void preorderTraversal(Binary* root) { if (root == NULL) { return; } printf("%d ", root->data); preorderTraversal(root->left); preorderTraversal(root->right); } // 中序遍历二叉树 void inorderTraversal(struct BinaryTreeNode* root) { if (root == NULL) { return; } inorderTraversal(root->left); printf("%d ", root->data); inorderTraversal(root->right); } // 后序遍历二叉树 void postorderTraversal(struct BinaryTreeNode* root) { if(root == NULL) { return; } postorderTraversal(root->left); postorderTraversal(root->right); printf("%d ", root->data); } Binary* delete_node(Binary* root,int data) { if(root==NULL){ return root; } //查找指定数据的节点和它的父节点 Binary *node=NULL,*parent=NULL,*temp=root; while(temp!=NULL){ if(data==temp->data){ node=temp; break; } //当前节点为父节点,向其子节点查找 parent=temp; if(data<temp->data){ temp=temp->left; } else temp=temp->right; //可能查找不到指定数据的节点 if(node==NULL){ return node; } //检查当前待删节点是否符合条件 if(node->left==NULL||node->right==NULL){ Binary *subnode=NULL; if(node->left==NULL){ //待删节点左子树为空,用右子树替代 subnode=node->right; } else{ //待删节点右子树为空,用左子树替代 subnode=node->left; } } if(parent!=NULL){ if(parent->left==node) parent->left=subnode; else parent->right=subnode; } else{ //删除树的根节点 root=subnode; } return root; } //左右子树都存在,按中序遍历查找该节点替代节点 Binary *replacer=node,replacerparent=parent; //查找直接前驱 temp=node->left; while(temp!=NULL){ replacerparent=replacer; replacer=temp; temp=node->right; } //删除节点 replacerparent=replacer->data; if(parent!=NULL){ if(parent->left==node){ parent->left=replacer; } else parent->right=replacer; } replacer->left=node->left; replacer->right=node->right; node->left=NULL; node->right=NULL; } int main() { // 创建二叉树 struct BinaryTreeNode* root = NULL; int data; root = insertNode(root, 4); insertNode(root, 2); insertNode(root, 1); insertNode(root, 3); insertNode(root, 6); insertNode(root, 5); insertNode(root, 7); // 先序遍历二叉树 printf("先序遍历二叉树:"); preorderTraversal(root); printf("\n"); // 中序遍历二叉树 printf("中序遍历二叉树:"); inorderTraversal(root); printf("\n"); // 后序遍历二叉树 printf("后序遍历二叉树:"); postorderTraversal(root); printf("\n"); scanf("%d",&data); delete_node(root,data) return 0; }