【0】README
0.1)本文旨在理清二叉树的先中后序遍历, 以及如何建立二叉树等相关内容;
0.2)本文涉及代码均为原创;
0.3)本文中遍历后的打印结果,朋友您可以直接写出二叉树的节点构造出来;
Attention):
- A1)要建立二叉树或者普通树, 这就涉及到插入节点的问题; 进而涉及到找到插入到哪个父节点的哪个孩子问题(left or right);当然,我们可以抽取一个 find 方法出来找出父节点, find 方法的关键是 首先要对是否为空树进行测试;
- A2) 而且,你要知道,在后面的二叉查找树的 插入方法insert 和 我们的 二叉树或者普通树的插入方法是不同的, 因为二叉查找树的定义是 :“该树中的每个节点 X, 它的左子树中所有关键字值 小于 X 的关键字值, 而它的右子树中所有关键字值大于 X 的关键字值”; 换句话说,在二叉查找树中,节点之间是有大小关联的, 而在二叉树和其它普通树中,节点间的数值大小是没有关系的,任意的 (特别要注意);
【1】二叉树相关概念
1.1)定义:二叉树是一颗树,其中每个节点都不能有多余两个儿子;
1.2)重要性质:平均二叉树的深度要比N小得多(N是该二叉树的节点个数);
【2】二叉树的表示方法说明:
2.1)树一般画成圆圈并用一些直线连接起来,因为二叉树实际上就是图,但涉及到树时, 我们也不明显地画出 NULL 指针,因为具有N个节点的每一个二叉树都将需要 N+1 个 NULL 指针;
2.2)为什么是N+1个NULL 指针? 因为N个节点==2N个指针==N-1条边;故余下N+1条边为 NULL , 即N+1个指针为NULL;(除根节点root外,每个节点都对应一条边)
【3】对二叉树的先序 + 中序 + 后序遍历
Attention)对于二叉树的遍历,我们的简单想法是, 遍历后的结果,我可以画出该二叉树节点的构造;
3.1)先序遍历步骤:如果二叉树为空树, 则什么都不做; 否则:
- step1)访问根节点;
- step2)先序遍历左子树;
- step3)先序遍历右子树;
3.1.1)download source code : https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter4/p70_preorder_binary_tree.c
3.1.2)source code at a glance :
#include <stdio.h>
#include <malloc.h>#define ElementType char
#define Error(str) printf("\n error: %s \n",str) struct BinaryTree;
typedef struct BinaryTree *BinaryTree;BinaryTree createBinaryTree();
BinaryTree makeEmpty(BinaryTree t);
BinaryTree insert(ElementType e, BinaryTree t, int);// we adopt child-sibling notation
struct BinaryTree
{ElementType value;BinaryTree left;BinaryTree right;
};// create a BinaryTree with root node
BinaryTree createBinaryTree()
{ BinaryTree t;t = (BinaryTree)malloc(sizeof(struct BinaryTree));if(!t) {Error("out of space, from func createBinaryTree"); return NULL;} t->left = NULL;t->right = NULL; t->value = '/';return t;
}// make the BinaryTree empty
BinaryTree makeEmpty(BinaryTree t)
{if(t){makeEmpty(t->left);makeEmpty(t->right); free(t);} return NULL;
}//insert a Tree node with value e into left child or right child of the parent
BinaryTree insert(ElementType e, BinaryTree parent, int isLeft)
{ BinaryTree node;if(!parent){Error("for parent BinaryTree node is empty , you cannot insert one into the parent node, from func insert"); return NULL;}node = (BinaryTree)malloc(sizeof(struct BinaryTree));if(!node) {Error("out of space, from func insert"); return NULL;}node->value = e;node->right = NULL;node->left = NULL;// building the node with value e overif(isLeft) { // the tree node inserting into left child of the parent if(parent->left) {Error("for parent has already had a left child , you cannot insert one into the left child, from func insert"); return NULL; }parent->left = node;}else { // the tree node inserting into right child of the parent if(parent->right) {Error("for parent has already had a right child , you cannot insert one into the right child, from func insert"); return NULL; }parent->right = node;} return node;
}// find the BinaryTree root node with value equaling to e
BinaryTree find(ElementType e, BinaryTree root)
{BinaryTree temp;if(root == NULL)return NULL;if(root->value == e)return root;temp = find(e, root->left); if(temp) return temp;elsereturn find(e, root->right);
}// analog print directories and files name in the BinaryTree, which involves postorder traversal.
void printPreorder(int depth, BinaryTree root)
{ int i;if(root) { for(i = 0; i < depth; i++)printf(" "); printf("%c\n", root->value);printPreorder(depth + 1, root->left); printPreorder(depth + 1, root->right); // Attention: there's difference between traversing binary tree and common tree }else {for(i = 0; i < depth; i++)printf(" "); printf("NULL\n");}
}int main()
{BinaryTree BinaryTree;BinaryTree = createBinaryTree();printf("\n ====== test for postordering the BinaryTree presented by left_right_child structure ====== \n"); printf("\n test for respectively inserting 'A' and 'B' into left and right child of the parent '/' , then 'C' and 'D' into the left and right child of the parent 'A' \n"); insert('A', find('/', BinaryTree), 1); // 1 means left childinsert('B', find('/', BinaryTree), 0); // 0 means right childinsert('C', find('A', BinaryTree), 1);insert('D', find('A', BinaryTree), 0);printPreorder(1, BinaryTree);printf("\n test for respectively inserting 'A' and 'B' into left and right child of the parent '/' \n"); insert('E', find('/', BinaryTree), 1);insert('F', find('/', BinaryTree), 0);printPreorder(1, BinaryTree); printf("\n test for inserting 'E' into the right child of the parent 'B' , then repectively 'F' and 'G' into the left and right child of the parent 'H' \n"); insert('E', find('B', BinaryTree), 0); insert('F', find('E', BinaryTree), 1);insert('G', find('E', BinaryTree), 0);printPreorder(1, BinaryTree); /**/return 0;
}
3.2)中序遍历步骤:如果二叉树为空树, 则什么都不做; 否则:
- step1)中序遍历左子树;
- step2)访问根节点;
- step3)中序遍历右子树;
3.2.1)download source code : https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter4/p70_inorder_binary_tree.c
3.2.2)source code at a glance :(Attention:要知道前序+中序+后序遍历的源代码的唯一不同是 打印函数的不同,这里,我们只给出中序的打印函数,其他的函数同前序是一样的,这里不再重复给出, 同时我们的后序遍历代码也只是给出了打印函数,其他函数同前序遍历一样,下文不再累述)
// analog print directories and files name in the BinaryTree, which involves postorder traversal.
void printInorder(int depth, BinaryTree root)
{ int i;if(root) { printInorder(depth + 1, root->left); for(i = 0; i < depth; i++)printf(" "); printf("%c\n", root->value);printInorder(depth + 1, root->right); // Attention: there's difference between traversing binary tree and common tree }else {for(i = 0; i < depth; i++)printf(" "); printf("NULL\n");}
}
3.3)后序遍历步骤:如果二叉树为空树, 则什么都不做; 否则:
- step1) 后序遍历左子树;
- step2) 后序遍历右子树;
- step3) 访问根节点;
3.3.1)download source code: https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter4/p70_postorder_binary_tree.c
3.3.2)source code at a glance:
// analog print directories and files name in the BinaryTree, which involves postorder traversal.
void printPostorder(int depth, BinaryTree root)
{ int i;if(root) { printPostorder(depth + 1, root->left); printPostorder(depth + 1, root->right); // Attention: there's difference between traversing binary tree and common treefor(i = 0; i < depth; i++)printf(" "); printf("%c\n", root->value); }else {for(i = 0; i < depth; i++)printf(" "); printf("NULL\n");}
}