对于二叉树的操作通常采用迭代的方法。
常用二叉树的结构一般为:
- typedef struct TreeNode
- {
- elemtype val;
- struct TreeNode *left;
- struct TreeNode *right;
- }
1、创建二叉树 / 元素插入
创建二叉树,实际上就是将元素一个一个地插入到二叉树中,因此可以在创建二叉树的主程序中循环调用插入函数来实现创建的目的。
在将元素插入到二叉树的过程中首先要注意的是当二叉树为空树的情况;
其次如果希望通过返回值改变二叉树的话,输入只需要为头结点指针以及相应的插入元素值即可,但是如果希望直接修改传入的指针,则输入应该为指向头结点的指针的指针。
- TreeNode* InsertElem(TreeNode *head, elemtype x)
- {
- if( head == NULL)
- {
- TreeNode *p = (TreeNode*)malloc(sizeof(TreeNode));
- p->val = x;
- p->left = NULL;
- p->right = NULL;
- head = p;
- return head;
- }
- else if(head->val > x)
- head->left = InsertElem( head->left, x);
- else
- head->right = InsertElem( head->right, x);
- return head;
- }
这里没有考虑有相同元素的问题,如果有相同元素,可以对上述代码稍作修改,或者修改树的节点,增加一个计数变量。
2、删除整个二叉树
删除二叉树的过程中需要注意的是,在删除之后,头指针的值应该复制为NULL,避免头指针成为野指针。同样的,返回值应该复制给二叉树的头指针,否则传入的参数应该为指向头指针的指针。
- TreeNode* MakeEmpty( TreeNode *head)
- {
- if (head != NULL)
- {
- MakeEmpty(head->left);
- MakeEmpty(head->right);
- free(head);
- }
- return NULL;
- }
3、遍历二叉树
二叉树的遍历有两个大类,包括深度遍历与广度遍历。
深度遍历又包括常见的前序遍历(根左右)、中序遍历(左根右)与后序遍历(左右根),具体的记忆可以根据遍历根节点的先后来记忆。并且根据前序遍历与中序遍历可以推断后序遍历,根据中序遍历与后序遍历可以推断前序遍历,这里一定要包括中序遍历。
广度遍历是先遍历完同一层次的所有节点之后,再遍历下一个层次的节点。
前序遍历 + 中序遍历 + 后序遍历
- void Preorder(TreeNode *tree)//前序遍历
- {
- if (tree == NULL )
- return;
- cout << tree->val;
- Preorder(tree->left);
- Preorder(tree->right);
- }
- void Inorder(TreeNode* tree)//中序遍历
- {
- if (tree == NULL )
- return;
- Preorder(tree->left);
- cout << tree->val;
- Preorder(tree->right);
- }
- void Postorder(TreeNode* tree)、、
- {
- if (tree == NULL )
- return;
- Preorder(tree->left);
- Preorder(tree->right);
- cout << tree->val;
- }
寻找最值包括寻找最大值与最小值,他们的方法是一样的,对于在二叉树中寻找最小值,可以一直遍历二叉树的左子树,知道左子树的左子树为空。
- TreeNode* FindMin(TreeNode *head)//寻找二叉树中的最小值
- {
- TreeNode *tmp = head;
- assert(tmp != NULL);
- while (tmp->left != NULL)
- {
- tmp = tmp->left;
- }
- return tmp;
- }
在这里设置一个tmp指针,主要是为了避免直接在头结点上操作修改头指针。
5、寻找元素
- TreeNode* SearchElem(TreeNode *head, elemtype x)
- {
- if (head == NULL)
- return head;
- if (head->val > x)
- return SearchElem(head->left, x);
- else if (head->val < x)
- return SearchElem(head->right, x);
- else
- return head;
- }
删除一个元素,首先要调用上述元素寻找函数找到相应的函数,这里尤其要注意元素没有找到的特殊情况。
如果找到了相应的元素,则需要考虑该元素是否为叶节点、度为1、度为2.
- extern TreeNode* FindMin(TreeNode *tree);
- TreeNode* DeleteElem(TreeNode *tree, int x)
- {
- if( tree == NULL)
- cerr << "Elem not found";
- if (x < tree->val)
- tree->left = DeleteElem(tree->left, x);
- else
- if (x > tree->val)
- tree->right = DeleteElem(tree->right, x);
- else//找到节点
- {
- if ( tree->left != NULL && tree->right != NULL)//节点的左右子树都不为空
- {
- TreeNode *minTmp = FindMin(tree->right);
- tree->val = minTmp->val;
- tree->right = DeleteElem(tree, tree->val);
- }
- else
- {
- TreeNode *tmpCell = tree;
- if (tree->right == NULL)
- tree = tree->left;
- else if (tree->left == NULL)
- tree = tree->right;
- free(tmpCell);
- }
- }
- return tree;
- }