二叉查找树非递归实现

一、二叉查找树概念

二叉查找树也称二叉排序树、二叉搜索树,它有如下特点:

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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值