二叉树的一些通用算法,包括前、中、后、层遍历,查找指定节点/父节点,求树高,最大最小节点、两节点最近公共父节点,任一节点到根的路径,任一节点在树中的层次等。
int element[] = {0,4,5,6,3,1,9,8,7,2,10,}; // 4,5,6,3,1,9,8,7,2,10
#define MAX(a,b) ((a)>(b))?(a):(b)
#define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0])
bool isLeaf(BinaryTree* root)
{
if(root->left == NULL && root->right == NULL) // leaf
return true;
else
return false;
}
bool hasBothChild(BinaryTree* root)
{
if(root->left != NULL && root->right != NULL)
return true;
else
return false;
}
bool hasOnlyLeftChild(BinaryTree* root)
{
if(root->left != NULL && root->right == NULL)
return true;
else
return false;
}
bool hasOnlyRightChild(BinaryTree* root)
{
if(root->left == NULL && root->right != NULL)
return true;
else
return false;
}
int getMaxElement(BinaryTree* root)
{
if(root->left == NULL && root->right == NULL) // leaf
return root->data;
else
{
if(root->left != NULL && root->right != NULL)
return MAX(getMaxElement(root->left), getMaxElement(root->right));
else if(root->left == NULL)
return getMaxElement(root->right);
else
return getMaxElement(root->left);
}
}
int getBinaryTreeHeight(BinaryTree* root)
{
if(root->left == NULL && root->right == NULL) // leaf
return 1;
else
{
if(root->left != NULL && root->right != NULL)
return MAX(getBinaryTreeHeight(root->left)+1, getBinaryTreeHeight(root->right)+1);
else if(root->left == NULL)
return getBinaryTreeHeight(root->right) + 1;
else
return getBinaryTreeHeight(root->left) + 1;
}
}
void preOrderBinaryTree(BinaryTree* root)
{
if(root != NULL)
{
printf("%5d",root->data);
preOrderBinaryTree(root->left);
preOrderBinaryTree(root->right);
}
}
void midOrderBinaryTree(BinaryTree* root)
{
if(root != NULL)
{
midOrderBinaryTree(root->left);
printf("%5d",root->data);
midOrderBinaryTree(root->right);
}
}
void postOrderBinaryTree(BinaryTree* root)
{
if(root != NULL)
{
postOrderBinaryTree(root->left);
postOrderBinaryTree(root->right);
printf("%5d",root->data);
}
}
void levelOrderBinaryTree(BinaryTree* root)
{
Queue queue;
queue.front = 0;
queue.rear = 0;
queue.queue[0] = root;
++queue.rear;
puts("\nlevel order\n");
while(queue.front != queue.rear)
{
BinaryTree* current = queue.queue[queue.front++];
printf("%5d",current->data);
if(current->left != NULL)
{
queue.queue[queue.rear++] = current->left;
}
if(current->right != NULL)
{
queue.queue[queue.rear++] = current->right;
}
}
}
BinaryTree* searchNodeFromBinaryTree(BinaryTree* root, int data)
{
if(root->data == data)
return root;
if(root->left == NULL && root->right == NULL && root->data != data) // leaf
return NULL;
BinaryTree* left = NULL;
BinaryTree* right = NULL;
if(root->left != NULL)
left = searchNodeFromBinaryTree(root->left, data);
if(root->right != NULL)
right = searchNodeFromBinaryTree(root->right, data);
if(left == NULL && right == NULL) // no data on this branch
return NULL;
else if(left == NULL)
return right;
else
return left;
}
BinaryTree* searchFatherNode(BinaryTree* root, int data)
{
if(isLeaf(root)) // must judge leaf first
return NULL;
if(((root->left != NULL) && (root->left->data == data)) || ((root->right != NULL) && (root->right->data == data))) // find
return root; // attention, left child or right child maybe NULL, therefore, must judge if it exist
BinaryTree* left = NULL;
BinaryTree*
right = NULL;
if(root->left != NULL)
left = searchFatherNode(root->left, data);
if(root->right != NULL)
right = searchFatherNode(root->right, data);
if(left == NULL && right == NULL) // no data on this branch
return NULL;
else if(left == NULL)
return right;
else
return left;
}
void printPathFromRootToCurrent(BinaryTree* root, int data, int* height)
{
Stack st;
st.top = 0;
BinaryTree* node = searchNodeFromBinaryTree(root,data);
st.stack[st.top++] = node;
while(node != root) // not reach root
{
node = searchFatherNode(root, node->data);
st.stack[st.top++] = node;
} // push
if(height != NULL) // return the height of the node
{
*height = st.top;
return;
}
while(st.top != 0)
{
printf("%5d",st.stack[--st.top]->data);
} // pop print the path
}
int getNodeHeight(BinaryTree* root, int data)
{
int height;
printPathFromRootToCurrent(root, data, &height);
return height;
}
bool isYourAncestor(BinaryTree* root, int data)
{
if(isLeaf(root))
return false;
if(((root->left != NULL) && (root->left->data == data)) || ((root->right != NULL) && (root->right->data == data)))
return true;
bool left = false;
bool right = false;
if(root->left != NULL)
left = isYourAncestor(root->left, data);
if(root->right != NULL)
right = isYourAncestor(root->right, data);
return left||right;
}
BinaryTree* searchCommonFatherNode(BinaryTree* root, int m, int n)
{
int firstNodeHeight = getNodeHeight(root, m);
int secondNodeHeight = getNodeHeight(root, n);
BinaryTree* currentNode;
if(firstNodeHeight <= secondNodeHeight) // find the shorter one
{
currentNode = searchNodeFromBinaryTree(root, m);
if(isYourAncestor(currentNode, n))
return currentNode;
else
{
while(currentNode != root)
{
currentNode = searchFatherNode(root, currentNode->data);
if(isYourAncestor(currentNode, n))
return currentNode;
}
return root;
}
}
else
{
currentNode = searchNodeFromBinaryTree(root, n);
if(isYourAncestor(currentNode, m))
return currentNode;
else
{
while(currentNode != root)
{
currentNode = searchFatherNode(root, currentNode->data);
if(isYourAncestor(currentNode, m))
return currentNode;
}
return root;
}
}
}
BinaryTree* createBinaryTree()
{
BinaryTree* root = (BinaryTree*)malloc(BinaryTreeLength);
root->data = element[1];
root->left = NULL;
root->right = NULL;
for(int i = 2; i < sizeof(element)/sizeof(element[0]); ++i)
{
BinaryTree* currentNode = (BinaryTree*)malloc(BinaryTreeLength);
currentNode->data = element[i];
currentNode->left = NULL;
currentNode->right = NULL;
BinaryTree* parentNode = searchNodeFromBinaryTree(root,element[i/2]);
if(i % 2 == 0) // left child
parentNode->left = currentNode;
else
parentNode->right = currentNode;
}
return root;
}
int getLeafCount(BinaryTree* root)
{
if(isLeaf(root))
return 1;
else
{
if(hasBothChild(root))
return getLeafCount(root->left) + getLeafCount(root->right);
else if(hasOnlyLeftChild(root))
return getLeafCount(root->left);
else
return getLeafCount(root->right);
}
}
int getNonLeafCount(BinaryTree* root)
{
static int m = 0;
static int n = 0;
if(isLeaf(root))
return 0;
if(root->left != NULL)
m = getNonLeafCount(root->left) + 1;
if(root->right != NULL)
n = getLeafCount(root->right) + 1;
return m+n;
}
void binaryTreeOperationMenu(void)
{
BinaryTree* root = createBinaryTree();
do
{
puts("\n*****************************************\n");
puts("* 1 pre order to visit a binary tree*******\n");
puts("* 2 mid order to visit a binary tree*******\n");
puts("* 3 post order to visit a binary tree *****\n");
puts("* 4 level order to visit a binary tree*****\n");
puts("* 5 the height of the binary tree**********\n");
puts("* 6 the max element of a binary tree*******\n");
puts("* 7 search a node from binary tree*********\n");
puts("* 8 search father node from binary tree****\n");
puts("* 9 print path from root to current node***\n");
puts("* 10 search the common father node*********\n");
puts("* 11 count of leaf*************************\n");
puts("* 12 count of non-leaf*********************\n");
puts("* 13 print the path from root**************\n");
puts("* 14 quit**********************************\n");
puts("*******************************************\n");
int choice;
int data;
BinaryTree* node = NULL;
scanf("%d",&choice);
switch(choice)
{
case 1:
preOrderBinaryTree(root);
break;
case 2:
midOrderBinaryTree(root);
break;
case 3:
postOrderBinaryTree(root);
break;
case 4:
levelOrderBinaryTree(root);
break;
case 5:
printf("\n the height is %d\n",getBinaryTreeHeight(root));
break;
case 6:
printf("\n the max element is %d\n",getMaxElement(root));
break;
case 7:
puts("\n input the data you wannna search\n");
scanf("%d",&data);
node = searchNodeFromBinaryTree(root,data);
if(node == NULL)
puts("\ndoes not exists\n");
else
puts("\nexists\n");
break;
case 8:
puts("\n input the data you wannna search its father\n");
scanf("%d",&data);
node = searchFatherNode(root,data);
if(node == NULL)
puts("\n node does not exists or you have put a root\n");
else
printf("\n%d father is %d\n", data, searchFatherNode(root, data)->data);
break;
case 9:
break;
case 10:
int firstValue,secondValue;
puts("\n input first and second value\n");
scanf("%d,%d",&firstValue,&secondValue);
printf("\n the nearest common father of %d and %d is %d\n", firstValue, secondValue, searchCommonFatherNode(root, firstValue, secondValue)->data);
break;
case 11:
printf("\n the count of leaf is %d\n",getLeafCount(root));
break;
case 12:
printf("\n the count of non-leaf is %d\n",getNonLeafCount(root));
break;
case 13:
puts("\n input the node you wanna print\n");
scanf("%d",&data);
puts("the path is the following:\n");
printPathFromRootToCurrent(root,data, NULL);
break;
case 14:
exit(0);
default:
break;
}
} while(true);
}