所谓建立排序二叉树就是,就是将各结点数据元素顺序插到一棵二叉树中,在插入的过程中,始终保持二叉树中每个结点的值都大于其左子树上每个结点的值,而小于或等于其右子树上每个结点的值,每个结点信息包括结点数据(结点值)、左子树指针、右子树指针。
程序执行的过程中,bt指针始终指向根结点,p指针指向当前已找到的结点,q指针不断向下寻找新的结点。
为实现二叉树的非递归算法,需要设置一个栈来保存指向结点的指针,以便在遍历某结点的左子树后,由这个指针能找到该结点的右子树。栈中的地址是随着结点的遍历次序而动态变化的。
二叉树的结点小于等于2. 插入过程还可以看到,每次插入的新结点都是二叉排序树的新的叶子结点,在进行插入操作时,不必移动其他结点,仅需改动某个结点的指针,由空变为非空即可。
以下是参考http://blog.csdn.net/AmiRural/archive/2005/09/12/477834.aspx改写的程序代码,包括了递归的实现和我自己的实现方法。在vc6下调试过了,把代码考下来再看清晰些儿,在这看起来乱七八糟的。
参考程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX 100
#define INPUT_END -1
#define ERR -1
#define SZ 1024
int counter=0;
int stack[MAX],top=0;
typedef struct btreenode
{
int data;
struct btreenode *lchild;
struct btreenode *rchild;
}bnode;
typedef struct
{
bnode* vec[MAX];
int head, tail;
}myque;
void push_node(int s)
{
top++;
stack[top]=s;
}
int pop_node(void)
{
top--;
return(stack[top+1]);
}
bnode *creat_root(int x) //建立一个只有根结点的二叉树
{
bnode *p;
p=(bnode*)malloc (sizeof(bnode));
if (p != NULL)
{
p->data=x;
p->lchild = NULL;
p->rchild = NULL;
}
return(p);
}
bnode *inslchild(bnode *p,int x) //x作为左孩子插入到二叉树中
{
bnode *q;
if(p==NULL)
{
printf("Illegal insert.");
return NULL;
}
q = (bnode*)malloc(sizeof(bnode));
if (q != NULL)
{
q->data = x;
q->lchild=NULL;
q->rchild=NULL;
p->lchild=q; //x做为p <script src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js" type="text/javascript"></script> 的左孩子
}
return q;
}
bnode *insrchild(bnode *p,int x)
{
bnode *q;
if(p==NULL)
{
printf("Illegal insert.");
return NULL;
}
q = (bnode*)malloc(sizeof(bnode));
if (q != NULL)
{
q->data=x;
q->lchild=NULL;
q->rchild=NULL;
p->rchild=q; //x作为p的右孩子
}
return q;
}
void prorder(bnode *p) //输出二叉树的结构
{
if(p==NULL)
return;
printf("%d/t%u/t%d/t%u/t%u/n",++counter,p,p->data,p->lchild,p->rchild);
if(p->lchild!=NULL)
prorder(p->lchild);
if(p->rchild!=NULL)
prorder(p->rchild);
}
void print(bnode *p) //嵌套括号表示二叉树,输出左子树前打印左括号,
{ //输出右子树后打印右括号。
if(p!=NULL)
{
printf("%d",p->data);
if(p->lchild!=NULL||p->rchild!=NULL)
{
printf("(");
print(p->lchild);
if(p->rchild!=NULL)
printf(",");
print(p->rchild);
printf(")");
}
}
}
void preorder(bnode *p) //前序遍历
{
while(p!=NULL||top!=0)
{
if(p!=NULL)
{
printf("%d ",p->data); //输出结点值
push_node((int)p); //将指针值压入栈中
p=p->lchild; //遍历左子树
}
else
{
p=(bnode*)pop_node();
p=p->rchild; //遍历右子树
}
}
}
void inorder(bnode *p) //压栈实现中序遍历
{
while(p!=NULL||top!=0)
{
while(p!=NULL)
{
push_node((int)p); //将根结点压入栈中
p=p->lchild; //遍历左子树
}
p=(bnode*)pop_node();
printf("%d ",p->data); //输出当前结点值
p=p->rchild; //遍历右子树
}
}
void my_preorder_stack(bnode *p)
{
if (p == NULL)
{
return;
}
top = 0;
while (p != NULL || top != 0)
{
if(p != NULL)
{
printf("%d ", p->data);
push_node((int)p);
p = p->lchild;
}
else
{
p = (bnode*)pop_node();
p = p->rchild;
}
}
}
void my_inorder_stack(bnode *p)
{
if (p == NULL)
{
return;
}
top = 0;
while (p != NULL || top != 0)
{
while(p != NULL)
{
push_node((int)p);
p = p->lchild;
}
p = (bnode*)pop_node();
printf("%d ", p->data);
p = p->rchild;
}
}
void my_postorder_stack(bnode *p) //栈实现后序遍历
{
bnode *t = NULL;
top = 0;
if (p == NULL)
{
return;
}
while (p != NULL || top != 0)
{
while(p != NULL)
{
push_node((int)p);
p = p->lchild;
}
p = (bnode*)pop_node();
//如果右孩子为空或者已经遍历过了,就打印该节点数据
if (p->rchild == NULL || p->rchild == t)
{
printf("%d ", p->data);
t = p;
p = NULL;
}
else
{
push_node((int)p);
p = p->rchild;
}
}
}
void my_inorder(bnode *p) //递归实现中序遍历
{
if (p == NULL)
{
return;
}
if (p->lchild != NULL)
{
inorder(p->lchild);
}
printf("%d ", p->data);
if (p->rchild != NULL)
{
inorder(p->rchild);
}
}
void que_add(myque *q, bnode *p)
{
/* 当队列满时,头head和尾tail之间总存在一个空闲空间,它是为了区分栈满于栈空 */
if((q->tail+1)%MAX == q->head)
{
printf("queue overflow!/n");
}
else
{
q->vec[q->tail] = p;
q->tail = (q->tail + 1) % MAX;
}
}
bnode* que_del(myque *q)
{
bnode* p = NULL;
if (q->tail == q->head)
{
printf("nothing for delete!/n");
}
else
{
p = q->vec[q->head];
q->head = (q->head + 1) % MAX;
}
return p;
}
int que_empty(myque *q)
{
return (q->tail == q->head) ? 1 : 0;
}
void my_translevel(bnode *p)
{
bnode *t;
myque *q;
if (p == NULL)
{
return;
}
q = (myque*)malloc(sizeof(myque));
if (q == NULL)
{
printf("malloc failure!/n");
}
memset(q, 0, sizeof(myque));
que_add(q, p);
while( !que_empty(q))
{
t = que_del(q);
assert(t!=NULL);
if (t->lchild != NULL)
{
que_add(q, t->lchild);
}
if (t->rchild != NULL)
{
que_add(q, t->rchild);
}
printf("%d ", t->data);
}
if (q != NULL) //释放内存
{
free(q);
q = NULL;
}
}
void my_postorder_recursive(bnode *p)
{
if (p == NULL)
{
return;
}
if (p->lchild != NULL)
{
my_postorder_recursive(p->lchild);
}
if (p->rchild != NULL)
{
my_postorder_recursive(p->rchild);
}
printf("%d ", p->data);
}
void postorder(bnode *p) //后序遍历
{
unsigned sign; //设置一个标志,记录结点从栈中弹出的次数
while(p!=NULL||top!=0)
{
if(p!=NULL)
{
push_node((int)p); //第1次遇到结点p时压入其指针值
push_node(1); //置标志为1
p=p->lchild; //遍历结点p的左子树
}
else
while(top!=0)
{
sign=pop_node();
p=(bnode*)pop_node();
if(sign==1) //sign=1表示仅走过p的左子树
{
push_node((int)p); //第2次压入结点p的指针值
push_node(2); //设置标志为2
p=p->rchild; //遍历p的右子树
break;
}
else if(sign==2) //sign=2表示p的左右子树都已走完
{
printf("%d ",p->data); //输出结点p的值
p=NULL;
}
} //while(top!=0)
} //while(p!=NULL||top!=0)
}
void translevel(bnode *p) //层次遍历
{
struct node
{
bnode *vec[MAX];
int front,rear;
}q;
q.front=q.rear=0;
if(p!=NULL)
printf("%d ",p->data);
q.vec[q.rear]=p; //结点指针进入队列
q.rear=q.rear+1;
while(q.front<q.rear) //队列不为空
{
p=q.vec[q.front]; //队头出队列
q.front=q.front+1;
if(p->lchild!=NULL) //输出左孩子,并入队列
{
printf("%d ",p->lchild->data);
q.vec[q.rear]=p->lchild;
q.rear=q.rear+1;
}
if(p->rchild!=NULL)
{
printf("%d ",p->rchild->data);
q.vec[q.rear]=p->rchild;
q.rear=q.rear+1;
}
}
}
void my_free(bnode *p) // 不要忘记释放内存
{
if (p == NULL)
{
return;
}
if (p->lchild != NULL)
{
my_free(p->lchild);
}
if (p->rchild != NULL)
{
my_free(p->rchild);
}
free(p);
}
int main(int argc, char* argv[])
{
bnode *r,*p;
int x=0, y=0;
int i = 0;
int a[10] = {10 , -50 , 23, 100, 250,
-40 , 200, 24, 50 , 400};
start:
i = 0;
while (1)
{
printf("Input root:");
scanf("%d",&x);
if (x >= 0 && x <=100)
{
break;
}
else
{
printf("The root value need to be in 0 to 100!/n");
}
}
r = creat_root(x);
if (r == NULL)
{
printf("Create root node failure!/n");
}
x = 0;
printf("Input other node:/n");
while(i<10)
{
//scanf("%d",&x);
x = a[i++];
// if (x == INPUT_END)
// {
// break;
// }
p = r;
while(1)
{
if (x == p->data)
{
printf("The node %d existed already!/n", x);
break;
}
else if (x < p->data)
{
if(p->lchild == NULL)
{
inslchild(p, x);
break;
}
else
{
p = p->lchild;
}
}
else
{
if (p->rchild == NULL)
{
insrchild(p, x);
break;
}
else
{
p = p->rchild;
}
}
}
}
p=r;
printf("structure of the binary tree:/n");
printf("number/taddress/tdata/tlchild/trchild/n");
prorder(p);
printf("/n");
print(p);
printf("/t输出左子树前打印左括号,输出右子树后打印右括号。/n");
printf("----------1 前序遍历二叉树---------- /n");
printf("----------2 中序遍历二叉树---------- /n");
printf("----------3 后序遍历二叉树---------- /n");
printf("----------4 层次遍历二叉树---------- /n");
printf("----------5 退出程序---------------- /n");
while (1)
{
printf("请选择遍历方式:");
scanf("%d",&x);
if (x == 5)
{
my_free(p);
break;
}
switch(x)
{
case 1:
preorder(p);
printf("/n");
break;
case 2:
inorder(p);
printf("/n");
break;
case 3:
postorder(p);
//printf("/n");
//my_postorder_stack(p);
//my_postorder_recursive(p);
printf("/n");
break;
case 4:
translevel(p);
printf("/n");
my_translevel(p);
printf("/n");
break;
default:
my_free(p);
goto start;
}
}
return 0;
}