// 二叉搜索树,以特定的规则来进行构建
// 1,所有节点中,该节点的左子树中的节点的键值 =< 该节点,右子树中节点的键值 >= 该节点.
// 2,当进行一次中序遍历,则会得到升序排列
#include <stdio.h>
#include <stdlib.h>
struct Node{
int key;
Node *parent, *left, *right;
};
Node *root, *NIL;
void insert_node(int k){
//插入节点,构建搜索树
Node *z;
z = (Node *)malloc(sizeof(Node));
z -> key = k;
z -> left = NIL;
z -> right = NIL;
Node *x = root;
Node *y = NIL;
while(x != NIL){ //寻找适当节点插入
y = x;
if(z->key < x->key){
x = x -> left;
}else{
x = x -> right;
}
}
z -> parent = y;
if(y == NIL){ //如果是null则为头节点
root = z;
}else{
if(z -> key < y -> key){
y -> left = z;
}else{
y -> right = z;
}
}
}
Node* search_node(int k, Node *node)
{
// 搜索指定元素
while(node != NIL && node -> key != k){
if(node -> key < k){
node = node -> right;
}else{
node = node -> left;
}
}
return node;
}
Node* treeMinimum(Node * node)
{
while(node->left != NIL){
node = node -> left;
}
return node;
}
Node* get_next_node(Node *node)
{
//获取中序遍历的下一个节点
if(node -> right != NIL){
// 如果该结点有右子节点,则找该右子节点最左侧的节点
return treeMinimum(node -> right);
}
Node *y = node -> parent; //不存在右节点时,下一个节点就是,以左子节点身份出现的父节点
while(y != NIL && y -> right == node){
node = y;
y = y -> parent;
}
return y;
}
void delete_node(Node *node)
{
Node *y; //要删除的对象
Node *x; //y的子节点
//确定要删除的节点
if(node -> right == NIL || node -> left == NIL){
y = node;
}else{
y = get_next_node(node);
}
// 确定y的子节点
if(y -> left != NIL){
x = y -> left;
}else{
x = y -> right;
}
if(x != NIL){
x -> parent = y -> parent;
}
if (y -> parent == NIL){
root = x;
}else{
if(y == y -> parent -> left){
y -> parent -> left = x;
}else{
y -> parent -> right = x;
}
}
if(y != node){
node -> key = y -> key;
}
free(y);
}
void norder_traversal(Node* node)
{
// 中序遍历
if(node == NIL){
return;
}
norder_traversal(node -> left);
printf("%d ", node -> key);
norder_traversal(node -> right);
}
void preorder_traversal(Node* node)
{
// 前序遍历
if(node == NIL){
return;
}
printf("%d ", node -> key);
preorder_traversal(node -> left);
preorder_traversal(node -> right);
}
void postorder_traversal(Node* node)
{
// 后续遍历
if(node == NIL){
return;
}
postorder_traversal(node -> left);
postorder_traversal(node -> right);
printf("%d ", node -> key);
}
int main(int argc, char const *argv[])
{
int n,element;
scanf("%d", &n);
for(int i = 0; i < n; i++){
scanf("%d", &element);
insert_node(element);
}
printf("前序遍历: ");
preorder_traversal(root);
printf("\n中序遍历:");
norder_traversal(root);
printf("\n后续遍历:");
postorder_traversal(root);
printf("\n");
Node *node = search_node(22, root);
printf("=======%d=========\n", node -> key);
if(node != NIL){
delete(node);
}else{
printf("no\n");
}
printf("删除节点后:\n前序遍历: ");
preorder_traversal(root);
printf("\n中序遍历:");
norder_traversal(root);
printf("\n后续遍历:");
postorder_traversal(root);
printf("\n");
return 0;
}
/*
测试数据
7
22 20 15 21 50 49 51
*/
输出结果为:
7
22 20 15 21 50 49 51
前序遍历: 22 20 15 21 50 49 51
中序遍历:15 20 21 22 49 50 51
后续遍历:15 21 20 49 51 50 22
=======22=========
删除节点后:
前序遍历: 0 20 15 21 50 49 51
中序遍历:15 20 21 0 49 50 51
后续遍历:15 21 20 49 51 50 0
为什么之前被删除的节点还存在,并且是0,很奇怪的是,在其他的机子上是垃圾数字。。。。