#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *left; struct node *right; }; typedef struct node* Node; //给一个数据,返回一个二叉树的节点 Node newNode(int data) { Node node=(Node)malloc(sizeof(struct node)); if(node==NULL) return NULL; node->data=data; node->left=NULL; node->right=NULL; return node; } //下面介绍一些简单的二叉树的操作代码: /*1.递归计算二叉树中的节点数 */ int size(Node root) { Node node=root; if (node==NULL) return 0; else return (size(node->left)+1+size(node->right)); } /*2.计算二叉树的深度 */ int maxDepth(Node root) { Node node=root; if (node==NULL) return 0; else { int depleft=maxDepth(node->left); int depright=maxDepth(node->right); return (depleft>depright)?(depleft+1):(depright+1); } } /*3.给定一个BST,返回最小的值,即最左端的值 */ int minValue(Node root) { Node current=root; /*循环,直到找到最左端的那个值,即为最小值,并返回*/ while (current->left != NULL) { current=current->left; } return current->data; } /*4.1 BST的查找操作,递归操作 */ Node SearchBST(Node root, int num) { Node node=root; if (node==NULL || node->data == num) return node; else if(node->data <num) return SearchBST(node->left,num); else return SearchBST(node->right,num); } /*4.2 BST的查找操作,非递归算法 */ Node SearchBSTNoRec(Node root, int num) { Node node=root; while (node != NULL) { if (node->data==num) return node; else if(node->data > num) node=node->left; else node=node->right; } return node; } /*5.1 BST的插入操作,递归算法 */ Node Insert(Node root, int num) { Node node=root; if(node==NULL) return newNode(num); else{ if(node->data > num) node->left=Insert(node->left,num); else if(node->data <num) node->right=Insert(node->right,num); return node; } } /*5.2 BST的插入操作,非递归算法 */ Node InsertNoRec(Node root, int num) { Node node=root; Node parent; if(node==NULL)//如果头节点为空,将该数据插入头节点 node=newNode(num); else{ while(node!=NULL){//寻找插入的位置 if(node->data==num)//如果存在该节点,直接返回 return node; else{ parent=node; //记录父节点位置,用于在该节点后插入数据 if(node->data >num) node=node->left; else node=node->right; } } node=newNode(num); if(parent->data>num) //根据父节点的值,确定插在其左节点或右节点 parent->left=node; else parent->right=node; } return node; } /*6.BST的删除操作,递归处理,该代码来自数据结构与算法分析 */ Node Delete(Node root, int num) { Node node=root; Node pTemp; if(node==NULL) fprintf(stderr,"Error!Try to delete a NULL tree "); else if(node->data > num) node->left=Delete(node->left,num); else if(node->data < num) node->right=Delete(node->right,num); else if (node->left!=NULL && node->right !=NULL){//要删除的节点有两个子节点 pTemp=Findmin(node->right);//找到该节点右子树的最小的那个节点,来代替这个被删除的节点 node->data=pTemp->data; node->right=Delete(node->data,node->right); } else{//有一个子节点或者是叶子节点 pTemp=node; if(node->left==NULL) node=node->right; else if(node->right==NULL) node=node->left; free(pTemp); } return node; } /*辅助函数,用于查找二叉树的最小值节点,并返回 */ Node Findmin(Node node) { Node current=node; /*循环,直到找到最左端的那个值,即为最小值,并返回*/ while (current->left != NULL) current=current->left; return current; } /*6.1 BST的删除操作,非递归处理 */ void DeleteNoRec(Node root, int num) { Node parent; Node node=root; Node node1,parent1; while(node!=NULL && node->data!=num){//寻找需要删除的节点 parent=node; if (num<node->data)node=node->left; else node=node->right; } if (node==NULL) {//如果没有找到该节点,返回错误 printf("num is not in the tree "); return; } if(node!=root){ if (node->left==NULL){//左节点为空,则将右节点代替原来的位置(包含叶子节点的情况) if(num<=parent->num) parent->left=node->right; else parent->right=node->right; free(node); } else if(node->right==NULL){//右节点为空,则将左节点代替原来的位置 if (num<=parent->num) parent->left=node->left; else parent->right=node->left; free(node); } else{//如果两个节点都不为空 node1=node->right; //寻找右子树最小的那个节点代替被删除的那个 while(node1->left!=NULL){ parent1=node1; node1=node1->left; } parent1->left=node1->left; node->data=node1->data; free(node1); } } else free(root); } /*7.1二叉树前序遍历,递归算法 */ void preOrderT(Node root) { Node node=root; if (node==NULL) return; printf("%d ",node->data); preOrderT(node->left); preOrderT(node->right); } /*7.2 二叉树前序遍历,非递归算法 */ void preOrderTNoRec(Node root) { Node node=root; stack<Node> s;//利用堆栈 //当节点不为空或者堆栈不为空进入循环体 while ((NULL != node) || !s.empty()){ if (NULL != node){ printf("%d ", node->data);//打印节点,并压入堆栈 s.push(node); node = node->left; } else { node = s.top(); //如果node为空,指向堆栈的顶端,并弹出该节点 s.pop(); node = node->right; } } } /*8.1 二叉树中序遍历,递归算法 */ void InOrderT(Node root) { Node node=root; if (node==NULL) return; InOrderT(node->left); printf("%d ", node->data); InOrderT(node->right); } /*8.2 二叉树中序遍历,非递归算法 */ void InOrderTNoRec(Node root) { Node node=root; stack<Node> s; //创建堆栈 //当节点不为空或堆栈不为空,进入循环体 while ((NULL != node) || !s.empty()){ if (NULL != node){ s.push(node);//压入节点,直到最左端的节点 node = node->left; } else{ node = s.top();//指向堆栈的顶端节点 printf("%d ", node->data);//输出该节点,并弹出,指向其右节点 s.pop(); node = node->right; } } } /*9.1 二叉树的后序遍历,递归算法 */ void PostOrderT(Node root) { Node node=root; if (node==NULL) return; PostOrderT(node->left); PostOrderT(node->right); printf("%d ",node->data); } /*9.2 二叉树的后序遍历,非递归算法 */ void PostOrderTNoRec(Node root) { Node node=root; stack<Node> s; Node pre=NULL; //如果节点不为空或堆栈不为空,进入循环体 while ((NULL != node) || !s.empty()){ if (NULL != node){//压入节点,直到最左端的非空节点 s.push(node); node = node->left; } else { node = s.top();//得到一个非空节点 if (node->right!=NULL && pre!=node->right){ //防止节点重复被遍历 node = node->right; } else{ node=pre=s.top();//得到一个节点,并输出,pre保存这个节点 printf("%d ", node->data); s.pop(); //弹出节点 node=NULL; } } } } /*10. 给定一个BST和一个数,检查是否存在一条路径,从叶子到根节点,使得每个节点的数据之和为这个数 *算法的思想:减去一个节点的值,然后递归求解 */ int hasPathSum(Node root, int sum) { Node node=root; //如果把树遍历完得到sum==0,返回true if (node==NULL){ return sum==0; } else{//对两个子树递归求解 int subSum=sum-node->data; return (hasPathSum(node->left) || hasPathSum(node->right)); } } /*11.给定一棵二叉树,打印所有根节点到叶子节点的路径 */ void printPaths(Node root) { int path[100]; printPathsRec(root,path,0); } /* *递归调用,打印出每条路径 */ void printPathsRec(Node node, int path[],len) { if (node==NULL) return; //将该节点加入路径中 path[len]=node->data; len++; //如果该节点是叶子节点,就输出路径 if (node->left==NULL && node->right==NULL){ printArray(path,len); } else{//否则,对左右节点递归调用 printPathsRec(node->left,path,len); printPathsRec(node->right,path,len); } } /*打印出一条路径*/ void printArray(int path[],int len) { int i; for (i=0;i<len;i++) printf("%d ",path[i]); printf(" "); } /* *12.对一棵二叉树交换其左右节点,使其看起来像以前的镜像,例如: 4 4 / / / / 2 5 is changed to 5 2 / / / / 1 3 3 1 */ void mirror(Node root) { Node node=root; if (node==NULL){ return; } else{ Node tmp; mirror(node->left); mirror(node->right); //交换左右节点 tmp=node->left; node->left=node->right; node->right=tmp; } } /*13.给定两个二叉树,看其是否完全相同 */ int sameTree(Node a,Node b) { if(a==NULL && b=NULL) return true; else if(a!=NULL && b!=NULL){ return (a->data==b->data && sameTree(a->left,b->left) && sameTree(a->right,b->right)); } else return false; } /*14.给定numKeys个不同的节点,计算能够构成多少棵BST *算法:考虑每个节点都可以作为根节点,递归计算其左右子树的个数 */ int countTrees(int numKeys) { if (numKeys<=1) return 1; else{ int sum=0,root,left,right; for (root=1;root<=numKeys;root++){ left=countTrees(root-1); right=countTrees(numKeys-root); //根据左右子树组合的可能,肯能的树的个数为left*right sum+=left*right; } return sum; } } /*15.1 isBST1(),检验一棵二叉树是不是BST */ int isBST1(Node node) { if (node==NULL) return true; //如果左子树的最小值大于当前的值,返回false if (node->left!=NULL && minValue(node->left) >node->data) return false; //如果右子树的最大值小于当前的值,返回false if (node->right !=NULL && maxValue(node->right) <=node->data) return false; //对左右子树递归调用 if (!isBST1(node->left) || !isBST1(node->right)) return false; return true; } /*15.2 isBST2(),检验一棵二叉树是不是BST(效率更高的版本) */ int isBST2(Node node) { return isBSTUtil(node,INT_MIN,INT_MAX); } int isBSTUtil(Node node, int min, int max) { if (node==NULL) return true; //如果这个节点不是在要求的范围之类,则返回false if (node->data < min || node->data > max) return false; else //对左右子树进行递归检查 return (isBSTUtil(node->left,min,node->data)&& isBSTUtil(node->right,node->data+1,max)); }