数据结构中排序算法- 二叉树排序(7)

1,二叉树排序算法

  • 基本思想:二叉排序树:要么是空树,要么满足以下条件:若左子树不空,则左子树所有结点的值均小于根结点的值,若右子树不空,右子树所有结点的值均大于根结点的值;左子树和右子树也是一颗二叉排序树。对于二叉排序树进行中序遍历,得到就是一个有序的序列。因此二叉树排序算法是:对于待排序列,把它构建一个二叉排序树,再进行中序遍历即可,那么重点就是如何构建一个二叉排序树。其实就是进行二叉排序树的查找,先构建一颗空树,第一个元素作为此树的根结点,从第二个元素开始在此树中查找,若不存在,则,根据二叉排序树的特性在叶子结点插入,直到最后一个元素。
  • 时间复杂度:nlog2(n)
  • 空间复杂度:中序遍历时,需要构建栈,为logn.

      这里有个很重要的点:按照二叉排序树的定义,我们是不可能在二叉排序树中看到两个或两个以上相同的元素存在,因为右>根>左;但是待排序列中的关键字总有一些是相同的,按照构建二叉排序树的方法,最后中序遍历,总有相同元素的被删掉,只保留其中一个,这样排序结果就是错的,也没法知道该算法的稳定性,那该怎么办?二叉树的插入操作是在二叉排序树中找不到的情况下插入的,这里要做些修改,就是在查找成功的条件下也要插入,怎么插入?把它插入到相同元素的的右孩子结点处,作为与其相同元素的右孩子,原来与其相同元素的右孩子插入在其右指针域,作为其右孩子。这样实际上是右>=根>左,中序遍历同样有序,并且是稳定的算法。


  • 基本操作:(1),二叉排序树的查找;(2),二叉排序树的插入;(3),二叉树的中序遍历;(4),初始化栈;(5),出栈和入栈。(6),动态内存管理。

     代码如下:

   

#include "StdAfx.h"
#include<stdio.h>
#include<malloc.h>
#define STACK_INCREMENT  10
#define STACK_INIT_SIZE 100
#define MAXSIZE         50

//二叉排序树的链式存储结构
typedef struct BiTNode
{
	int data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

//栈的顺序存储结构
typedef struct
{
	BiTree *base;
	BiTree *top;
	int stacksize;
}Sqstack;

//初始化一个栈,用于二叉树的中序遍历
void InitStack(Sqstack&S)
{
	S.base=(BiTree*)malloc(STACK_INIT_SIZE*sizeof(BiTNode));
	if(!S.base)
		exit(0);
	S.top=S.base;
	S.stacksize=STACK_INIT_SIZE;
}


//二叉排序树查找
void SearchBST(BiTree T,int key,BiTree f,BiTree&p)
{
	if(!T) 
		p=f;
	else if(T->data==key)
		p=T;
	else if(T->data<key)
		SearchBST(T->rchild,key,T,p);
	else 
		SearchBST(T->lchild,key,T,p);
}

//创建一个二叉排序树
void CreatBST(BiTree &T,int e)
{
	BiTree p,s,q;
	SearchBST(T,e,NULL,p);//找到带插入的位置。
	s=(BiTree)malloc(sizeof(BiTNode));
	s->data=e;
	s->lchild=NULL;
	s->rchild=NULL;
	if(!p)T=s;
	else if(e==p->data)//当待排序列中有相同的元素时,将其放在相同元素的右孩子位置。原来的右子树放在其右节点域。
	{
		q=p->rchild;
		p->rchild=s;
		s->rchild=q;
	}
	else if(e<p->data)
		p->lchild=s;
	else
		p->rchild=s;
}

//中序遍历二叉排序树
void InOrderTravese(BiTree T)
{
	BiTree p;
	Sqstack Sqt;
	InitStack(Sqt);
	p=T;
	while(p||Sqt.base!=Sqt.top)
	{
		if(p)
		{
			if(Sqt.top-Sqt.base>=Sqt.stacksize)
			{
				Sqt.base=(BiTree*)realloc(Sqt.base,(Sqt.stacksize+STACK_INCREMENT)*sizeof(BiTNode));
				if(!Sqt.base)
					exit(OVERFLOW);
				Sqt.top=Sqt.base+Sqt.stacksize;
				Sqt.stacksize+=STACK_INCREMENT;
			}
			*Sqt.top++=p;
			p=p->lchild;
		}
		else
		{
			p=*--Sqt.top;
			printf("%d ",p->data);
			p=p->rchild;
		}
	}
	printf("\n");
}
void main()
{
	int length;
	int bst[MAXSIZE];
	BiTree BST;
    BST=(BiTree)malloc(sizeof(BiTNode));
    BST=NULL;
	printf("***************************\n");
	printf("      二叉树排序算法       \n");
	printf("***************************\n");
	printf("请输入待排序序列的个数N (N<%d):",MAXSIZE);
	scanf("%d",&length);
	printf("\n");
	printf("请输入待排序的关键字:\n");
	for(int i=0;i<length;i++)
		scanf("%d",&bst[i]);
	printf("\n");
	for(int i=0;i<length;i++)
		CreatBST(BST,bst[i]);
	printf("输出二叉树排序结果:\n");
	InOrderTravese(BST);
	printf("\n");
	free(BST);
}


   运行结果示意图如下:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值