一、二叉查找树概念
二叉查找树也称二叉排序树、二叉搜索树,它有如下特点:
1、它是一个二叉树(不一定是完全二叉树)。
2、对于树上每个节点,如果存在左孩子,则左孩子的值比自己小,如果存在右孩子,则右孩子的值比自己大。
3、对于每个节点,它的左子树和右子树都是二叉查找树。
从以上特点可以总结出一个很重要的性质:中序遍历二叉查找树,将得到一个已排好序的序列。
另外二叉查找树在查找方面有优势,类似二分查找。
补充一点:本文将给出二叉树的非递归实现的第二种实现,即不使用栈的实现。其实使不使用栈实现遍历,其本质都是一样,就是如何在树结构中按照某种预先约定的方式(比如中序的方式)找到每个节点的前驱和后继,然后就想遍历单链表一样遍历树。
二、代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DATA_SIZE 10
#define STACK_INIT_SIZE 10
#define INCREASE_SIZE 10
typedef struct Node
{
int data;
struct Node *left;
struct Node *right;
struct Node *parent;
}Node;
typedef struct
{
Node **base;
int top;
int curlen;
}NodeStack;
int* init_data(int size);
void free_data(int *pdata);
void init_stack(NodeStack *s);
void free_stack(NodeStack *s);
int is_stack_empty(NodeStack s);
int is_stack_full(NodeStack s);
void push_node(NodeStack *s, Node *pnode);
Node* pop_node(NodeStack *s);
Node* create_bstree(int *pdata, int size);
void free_bstree(Node* t);
void visit_bstree(Node* t);<span style="white-space:pre"> </span>//利用栈实现树的非递归遍历
Node* find(Node *t, int elem);<span style="white-space:pre"> </span>//查找
int max(Node *t);<span style="white-space:pre"> </span>//寻找最大值
int min(Node *t);<span style="white-space:pre"> </span>//寻找最小值
Node* ldr_first(Node *t);//查找中序遍历是的第一个结点(即最左边的节点)
Node* ldr_prev(Node *n);//查找中序遍历中节点的前驱
Node* ldr_next(Node *n);//查找中序遍历中节点的后继
Node* ldr_last(Node *t);//查找中序遍历中树的最后一个节点(即最右边的节点)
void visit_no_stack_ascending(Node *t);//中序遍历(从左到右,升序,不用栈)
void visit_no_stack_descending(Node *t);//降序遍历(从右到左)
void del_elem(Node **t, int elem);//删除节点
int main()
{
puts("init data:");
int *pdata = init_data(DATA_SIZE);
if (!pdata)
{
return -1;
}
puts("create binary search tree:");
Node *t = create_bstree(pdata, DATA_SIZE);
if (!t)
{
return -1;
}
visit_bstree(t);
puts("Ascending order:");
visit_no_stack_ascending(t);
puts("Descending order:");
visit_no_stack_descending(t);
printf("the max is %d.\n", max(t));
printf("the min is %d.\n", min(t));
printf("Input the data you want to find:");
int elem;
scanf("%d", &elem);
if (!find(t, elem))
{
puts("cannot find.");
}
else
{
puts("find success.");
}
printf("Input the data you want to delete:");
scanf("%d", &elem);
del_elem(&t, elem);
puts("After delete:");
visit_no_stack_ascending(t);
free_bstree(t);
free_data(pdata);
return 0;
}
int* init_data(int size)
{
int *pdata;
pdata = (int*)malloc(size*sizeof(int));
if (!pdata)
{
return NULL;
}
srand(time(NULL));
int i;
for (i = 0 ; i < size ; ++i)
{
pdata[i] = rand()%100;
printf("%3d", pdata[i]);
}
printf("\n");
return pdata;
}
void free_data(int *pdata)
{
if (pdata)
{
free(pdata);
pdata = NULL;
}
}
Node* create_bstree(int *pdata, int size)
{
if (size <= 0)
{
return NULL;
}
Node *t = (Node*)malloc(sizeof(Node));
if (!t)
{
return NULL;
}
t->data = pdata[0];
t->left = NULL;
t->right = NULL;
t->parent = NULL;
int i;
for (i = 1 ; i < size ; ++i)
{
Node *tmp = (Node*)malloc(sizeof(Node));
if (!tmp)
{
break;
}
tmp->data = pdata[i];
tmp->left = NULL;
tmp->right = NULL;
tmp->parent = NULL;
Node *cur = t;
while (1)
{
if (tmp->data < cur->data)
{
if (cur->left)
{
cur = cur->left;
}
else
{
cur->left = tmp;
tmp->parent = cur;
break;
}
}
else if (tmp->data > cur->data)
{
if (cur->right)
{
cur = cur->right;
}
else
{
cur->right = tmp;
tmp->parent = cur;
break;
}
}
else
{
break;
}
}
}
return t;
}
void init_stack(NodeStack *s)
{
s->base = (Node**)malloc(STACK_INIT_SIZE*sizeof(Node*));
if (!s->base)
{
printf("Init stack error\n");
return ;
}
s->top = 0;
s->curlen = STACK_INIT_SIZE;
}
void free_stack(NodeStack *s)
{
if (s->base)
{
free(s->base);
s->base = NULL;
s->top = s->curlen = 0;
}
}
int is_stack_empty(NodeStack s)
{
return s.top <= 0;
}
int is_stack_full(NodeStack s)
{
return s.top >= s.curlen;
}
void push_node(NodeStack *s, Node *pnode)
{
if (is_stack_full(*s))
{
Node **tmp;
tmp = (Node**)realloc(s->base, (s->curlen+INCREASE_SIZE)*sizeof(Node*));
if (!tmp)
{
printf("push error\n");
free_stack(s);
return ;
}
s->curlen += INCREASE_SIZE;
}
(s->base)[s->top] = pnode;
(s->top)++;
}
Node* pop_node(NodeStack *s)
{
if (is_stack_empty(*s))
{
return NULL;
}
(s->top)--;
return (s->base)[s->top];
}
void free_bstree(Node* t)
{
if (!t)
{
return;
}
Node *curnode;
curnode = t;
NodeStack s;
init_stack(&s);
while (1)
{
if (curnode->left || curnode->right)
{
push_node(&s, curnode);
if (curnode->left)
{
curnode = curnode->left;
continue;
}
if (curnode->right)
{
curnode = curnode->right;
}
}
else
{
if (is_stack_empty(s))
{
printf("free node %d\n", curnode->data);
free(curnode);
break;
}
Node *tmp;
tmp = pop_node(&s);
if (curnode == tmp->left)
{
tmp->left = NULL;
}
if (curnode == tmp->right)
{
tmp->right = NULL;
}
printf("free node %d\n", curnode->data);
free(curnode);
curnode = tmp;
}
}
free_stack(&s);
}
void visit_bstree(Node* t)
{
if (!t)
{
return;
}
NodeStack s;
Node *curnode;
curnode = t;
init_stack(&s);
while (1)
{
if (curnode->left)
{
push_node(&s, curnode);
curnode = curnode->left;
continue;
}
printf("%3d", curnode->data);
if (curnode->right)
{
curnode = curnode->right;
}
else
{
Node *tmp;
tmp = NULL;
while (!is_stack_empty(s))
{
tmp = pop_node(&s);
printf("%3d", tmp->data);
if (tmp->right)
{
curnode = tmp->right;
break;
}
}
if (is_stack_empty(s) && (!tmp || !(tmp->right)))
{
break;
}
}
}
printf("\n");
free_stack(&s);
}
Node* find(Node *t, int elem)
{
Node *cur = t;
while (cur)
{
if (cur->data == elem)
{
return cur;
}
if (cur->data > elem)
{
cur = cur->left;
}
else
{
cur = cur->right;
}
}
if (!cur)
{
return NULL;
}
}
int max(Node *t)
{
Node *cur = t;
while (cur && cur->right)
{
cur = cur->right;
}
return cur->data;
}
int min(Node *t)
{
Node *cur = t;
while (cur && cur->left)
{
cur = cur->left;
}
return cur->data;
}
Node* ldr_first(Node *t)
{
if (!t)
{
return NULL;
}
Node *cur = t;
while (cur->left)
{
cur = cur->left;
}
return cur;
}
Node* ldr_prev(Node *n)
{
if (n->left)
{
return ldr_last(n->left);
}
if (n->parent)
{
if (n == n->parent->right)
{
return n->parent;
}
else
{
Node *cur = n->parent;
while (cur && cur->parent && cur == cur->parent->left)
{
cur = cur->parent;
}
return cur->parent;
}
}
else
{
return NULL;
}
}
Node* ldr_next(Node *n)
{
if (n->right)
{
return ldr_first(n->right);
}
if (n->parent)
{
if (n == n->parent->left)
{
return n->parent;
}
else
{
Node *cur = n->parent;
while (cur && cur->parent && cur == cur->parent->right)
{
cur = cur->parent;
}
return cur->parent;
}
}
else
{
return NULL;
}
}
Node* ldr_last(Node *t)
{
if (!t)
{
return NULL;
}
Node *cur = t;
while (cur->right)
{
cur = cur->right;
}
return cur;
}
void visit_no_stack_ascending(Node *t)
{
Node *cur = ldr_first(t);
while (cur)
{
printf("%3d", cur->data);
cur = ldr_next(cur);
}
printf("\n");
}
void visit_no_stack_descending(Node *t)
{
Node *cur = ldr_last(t);
while (cur)
{
printf("%3d", cur->data);
cur = ldr_prev(cur);
}
printf("\n");
}
void del_elem(Node **t, int elem)
{
Node *todel = find(*t, elem);
if (!todel)
{
puts("cannot find.");
return;
}
if (!todel->left && !todel->right)
{
if (todel->parent)
{
if (todel == todel->parent->left)
{
todel->parent->left = NULL;
}
else
{
todel->parent->right = NULL;
}
}
}
else if (todel->left && !todel->right)
{
Node *replace = todel->left;
if (todel->parent)
{
if (todel == todel->parent->left)
{
todel->parent->left = replace;
replace->parent = todel->parent;
}
else
{
todel->parent->right = replace;
replace->parent = todel->parent;
}
}
else
{
*t = replace;
}
}
else if (!todel->left && todel->right)
{
Node *replace = todel->right;
if (todel->parent)
{
if (todel == todel->parent->left)
{
todel->parent->left = replace;
replace->parent = todel->parent;
}
else
{
todel->parent->right = replace;
replace->parent = todel->parent;
}
}
else
{
*t = replace;
}
}
else <span style="font-family: Arial, Helvetica, sans-serif;">//当被删除节点同时拥有左右子树的时候,用待删除节点的直接后继代替待删除节点</span>
{
Node *replace = ldr_first(todel->right);
if (replace->right)
{
replace->parent->left = replace->right;
replace->right->parent = replace->parent;
}
else
{
replace->parent->left = NULL;
}
if (todel->parent)
{
if (todel == todel->parent->left)
{
todel->parent->left = replace;
replace->parent = todel->parent;
}
else
{
todel->parent->right = replace;
replace->parent = todel->parent;
}
}
else
{
replace->left = todel->left;
replace->right = todel->right;
*t = replace;
}
}
free(todel);
todel = NULL;
return;
}