赞
踩
1 二叉排序树定义:
如果它的左子树不为空,那么左子树上所有节点的值均小于它的根节点的值
如果它的右子树不为空,那么右子树上所有节点的值均大于它的根节点的值
根节点的左子树和右子树均是二叉排序树
(二叉排序树可能退化为链表,所以有平衡二叉树的概念;二叉排序树的中序遍历是从小到大有序的)
2 二叉排序树结构体及节点创建函数
- typedef struct Tree //二叉树
- {
- int data; //数据域
- struct Tree *left; //左子节点指针
- struct Tree *right; //右子节点指针
- } Tree;
- Tree *createBinarySortTreeNode(int data)
- {
- Tree *node = (Tree *)malloc(sizeof(Tree));
- node->data = data;
- node->left = NULL;
- node->right = NULL;
- return node;
- }
3 二叉排序树的节点插入
思路:将要插入节点的data与根节点data比较,如果小于根节点data,则插入根节点的左子树;如果大于根节点的data,则插入根节点的右子树;
插入子树相当于插入一个更小的树,因此可以用递归方法实现,直到找到没有子树的节点,将新节点插到其下面,成为叶子节点。
- void insertBinarySortTreeNode(Tree *dataNode, Tree **root) //二叉排序树插入节点,因为根节点可能改变,所以传二级指针
- {
- if (*root == NULL || dataNode == NULL)
- {
- *root = dataNode;
- return;
- }
- if (dataNode->data > (*root)->data)//如果插入节点大于原节点的data,插入节点需要放在root的右子树
- {
- if ((*root)->right == NULL)//找到插入位置
- {
- (*root)->right = dataNode;
- return;
- }
- if ((*root)->right)
- insertBinarySortTreeNode(dataNode, &(*root)->right);//递归找dataNode的插入位置
- }
- if (dataNode->data <= (*root)->data)//如果去掉等于号,表示不插入相同data的节点
- {
- if ((*root)->left == NULL)//找到插入位置
- {
- (*root)->left = dataNode;
- return;
- }
- if ((*root)->left)
- insertBinarySortTreeNode(dataNode, &(*root)->left); //递归找dataNode的插入位置
- }
- }

4 二叉排序树最大键值节点获取
- Tree *maxValueOfBinaryTree(Tree *root)
- {
- if (root == NULL)//空指针判断
- return NULL;
- Tree *pointer = root;
- while (pointer->right)//跳出循环后,pointer指向最后一个右子节点
- pointer = pointer->right;
- return pointer;
- }
5 二叉排序树最小键值节点获取(思路同上,不再赘述)
- Tree *minValueOfBinaryTree(Tree *root)
- {
- if (root == NULL)
- return NULL;
- Tree *pointer = root;
- while (pointer->left)
- pointer = pointer->left;
- return pointer;
- }
6 二叉排序树查找指定节点的父节点
- Tree *parentNodeOfBinaryTreeNode(Tree *dataNode, Tree *root) //获取dataNode节点的父节点
- {
- if (dataNode == NULL || root == NULL || root == dataNode) //空指针判断,以及root自身无父节点
- return NULL;
- Tree *pointer = root;
- Tree *parentNode = pointer;
- while (pointer != NULL && pointer->data != dataNode->data)
- {
- parentNode = pointer;
- if (dataNode->data > pointer->data)
- pointer = pointer->right;
- else
- pointer = pointer->left;
- } //每一次循环后parentNode总是pointer的父节点
- //循环跳出后,要么找到了dataNode,要么pointer为NULL了
- if (pointer == NULL)
- {
- printf("节点dataNode不存在\n");
- return NULL;
- }
- return parentNode;
- }

7 二叉排序树删除节点
代码如下
- void deleteBinarySortTreeNode(Tree *deleteNode, Tree **root) //删除二叉树中的某一个节点
- {
- Tree *parentOfDeleteNode = parentNodeOfBinaryTreeNode(deleteNode, *root); //删除节点的父节点
- if (deleteNode == NULL || root == NULL) //空指针判断
- return;
- if (deleteNode != *root && parentOfDeleteNode == NULL) //删除节点不是root,parentOfDeleteNode==NULL说明没有找到deleteNode或者树的root节点为NULL,直接结束;
- return;
- if (deleteNode->left == NULL && deleteNode->right == NULL) // case:1 删除节点为叶子节点的情况
- {
- if (*root == deleteNode) //删除的节点是root节点
- {
- *root = NULL;
- return;
- }
- if (parentOfDeleteNode->left == deleteNode)
- parentOfDeleteNode->left = NULL;
- if (parentOfDeleteNode->right == deleteNode)
- parentOfDeleteNode->right = NULL;
- }
- else if (deleteNode->left == NULL || deleteNode->right == NULL) // case:2 删除节点只有左子树或右子树,其中之一
- {
- if (*root == deleteNode)
- {
- if ((*root)->left != NULL) //删除节点为root节点,且root节点只有左子树
- (*root) = (*root)->left;
- else if ((*root)->right != NULL)
- (*root) = (*root)->right; //删除节点为root节点,且root节点只有右子树
- }
- else if (deleteNode->left != NULL) //删除节点只有左子树
- {
- if (parentOfDeleteNode->left == deleteNode) //删除节点是父节点的左子节点,且删除节点只有左子树
- parentOfDeleteNode->left = deleteNode->left; //把父节点的left指向deleteNode的左子节点
- if (parentOfDeleteNode->right == deleteNode)
- parentOfDeleteNode->right = deleteNode->left;
- }
- else if (deleteNode->right != NULL)
- {
- if (parentOfDeleteNode->left == deleteNode) //
- parentOfDeleteNode->left = deleteNode->right;
- if (parentOfDeleteNode->right == deleteNode)
- parentOfDeleteNode->right = deleteNode->right;
- }
- }
- else if (deleteNode->left != NULL || deleteNode->right != NULL) // case:3 删除节点有左子树和右子树
- {
- Tree *replaceNode = maxValueOfBinaryTree(deleteNode->left);
- //找到删除节点的左子树的最右节点(对应左子树的最大键值)作为替代节点,替代节点的键值与删除节点的键值是相邻的,
- Tree *parentOfReplaceNode = parentNodeOfBinaryTreeNode(replaceNode, *root); //获取替代节点的父节点
- if (*root == deleteNode)
- {
- parentOfReplaceNode->right = replaceNode->left;
- replaceNode->left = (*root)->left;
- replaceNode->right = (*root)->right;
- (*root) = replaceNode;
- }
- else if (parentOfDeleteNode->left == deleteNode) //删除节点是其父节点的左子节点
- {
- parentOfDeleteNode->left = replaceNode; //删除节点的父节点left指向替代节点
- replaceNode->left = deleteNode->left;
- if (parentOfReplaceNode != deleteNode)
- {
- replaceNode->right = deleteNode->right;
- //替代节点右子树指向删除节点右子树(如果替代节点父节点就是删除节点,deleteNode->right就是该替代节点,造成后面子树丢失;parentOfReplaceNode->right也没有意义)
- parentOfReplaceNode->right = replaceNode->left;
- }
- else if (parentOfReplaceNode == deleteNode)
- replaceNode->right = deleteNode->right->left; //替换节点的右子树指向了替换节点的左子树,看树图很容易理解
- }
- else if (parentOfDeleteNode->right == deleteNode) //删除节点是父节点的右子节点
- {
- parentOfDeleteNode->right = replaceNode; //删除节点的父节点right指向左子树最大键值对应节点
- replaceNode->right = deleteNode->right;
- if (parentOfReplaceNode != deleteNode)
- {
- replaceNode->left = replaceNode->left;
- parentOfReplaceNode->right = replaceNode->left;
- }
- else if (parentOfReplaceNode == deleteNode)
- replaceNode->left = replaceNode->left->left;
- }
- }
- free(deleteNode);
- }

8 中序遍历代码以及查找指定节点代码
- Tree *searchTreeNode(Tree *root, int value) //搜索二叉排序树含指定数据的节点
- {
- if (root == NULL)
- return NULL;
- if (root->data > value)
- return searchTreeNode(root->left, value);
- if (root->data < value)
- return searchTreeNode(root->right, value);
- else
- return root;
- }
- void inOrderList(Tree *root)//中序遍历
- {
- if (root == NULL)
- return;
- inOrderList(root->left);
- printf("%d->", root->data);
- inOrderList(root->right);
- }

9 函数测试与运行结果
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- int main()
- {
- int array[] = {2, 6, 9, 8, 12, 3, 5, 4, 0, -66, 1, -88};
- Tree root = {2, NULL, NULL};
- Tree *pointer = &root;
- for (int i = 1; i < sizeof(array) / sizeof(array[0]); i++)
- {
- Tree *node = createBinarySortTreeNode(array[i]);
- insertBinarySortTreeNode(node, &pointer);//插入节点
- }
- inOrderList(&root); //二叉排序树中序遍历
- puts("");
- Tree *maxNode = maxValueOfBinaryTree(&root);//最大键值节点查找
- printf("the maxValueNode:{data:%d left:%p right:%p}\n", maxNode->data, maxNode->left, maxNode->right);
- Tree *minNode = minValueOfBinaryTree(&root);//最小键值节点查找
- printf("the minValueNode:{data:%d left:%p right:%p}\n", minNode->data, minNode->left, minNode->right);
- Tree *searchNode = searchTreeNode(&root, 6);//查找指定节点
- printf("searchNode->{data:%d left:%p right:%p}\n", searchNode->data, searchNode->left, searchNode->right);
- Tree *parentNode = parentNodeOfBinaryTreeNode(searchNode, &root);//指定节点的父节点查找
- printf("parentNode->{data:%d left:%p right:%p} searchNode:%p\n", parentNode->data, parentNode->left, parentNode->right, searchNode);
- //如果测试删除root节点,需要把上行printf里面的parentNode的data去掉,因为是NULL,无法解引用
- Tree *pointer2 = &root;
- deleteBinarySortTreeNode(searchNode, &pointer2);//删除指定节点
- printf("删除节点searchNode节点后: ");
- inOrderList(pointer2);//中序遍历
- return 0;
- }

运行结果如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。