【数据结构1】(查询二叉树的实现)

理论解释:

http://www.cnblogs.com/skywang12345/p/3576328.html

很详细。不过函数实现略微复杂,不容易看懂。


函数实现:

http://www.cnblogs.com/elleniou/archive/2012/05/03/2480042.html

简单清晰。不过注释比较少,要认真看一会。


本人所用的测试代码是基于第二个链接,详细的步骤解释,参看代码

一、创建

#include "stdafx.h"
#include <iostream>

using std::cout;
using std::cin;
using std::endl;

struct tree // 其实该结构体应该是节点(Node,很多参考资料都有Node结构体)。但是理解为子树更容易理解操作过程,所以定义为tree是别有用心的
{
	int key; // 关键字,用于排序和查找
	tree* left; // 设置为指针确有妙处!
	tree* right;
	
};

// * 二叉查找树的类
class BTree // 这个BTree的B是binary search tree的B
{
public:
	tree* root;
	BTree(){ root = NULL; } // 初始化
	void create_bstree(int);
	void printTree(tree* subtree);

};

// * 类函数的实现
void BTree::create_bstree(int key)
{
	tree* new_node = new tree; // 使用new申请内存空间
	new_node->key = key; // 将新输入的数值包装成一个子树
	new_node->left = new_node->right = NULL;

/* 判断当前的数是不是空树 */
	if( root == NULL )
		root = new_node;
	else // 不是空树则开始比较数值,判断新输入 new_node 的合适位置
	{
		tree* back = NULL;
		tree* current = root; // 指针current指向了root,current的修改都会影响到root,两个指针都是指向这个地址
					 	  //(不是两指针相等而是两个指针指向的内容相等)
		while(current!=NULL) // 判断new_node需要放置的节点(此刻还是叶子)
        {
			back = current; // 控制循环次数
			if(current->key > key) // 应该是左侧
				current = current->left;
			else
				current = current->right;
		}
		// 获得
		if(back->key >key) // 决定new_node的左右位置
			back->left = new_node;
		else
			back->right = new_node;
		}
}

// * 显示函数(有些不太直观,不过可以证明,树已经建立)
void printTree(tree* subtree)
{
	if(subtree->right != NULL && subtree->left != NULL)
	{
		cout<<subtree->key<<endl;
		if(subtree->right->key == NULL)
			cout<<"右儿子 = NULL"<<endl;
		else
			cout<<"右儿子"<<subtree->right->key<<endl;	
		if(subtree->left->key == NULL)
			cout<<"左儿子 = NULL"<<endl;
		else
			cout<<"左儿子"<<subtree->left->key<<endl;	

		printTree(subtree->right);
		printTree(subtree->left);
	}
}


int _tmain()
{
	BTree A;
	int array[]={7,4,2,3,15,35,6,45,55,20,1,14,56,57,58};
	int k;     
	k = sizeof(array)/sizeof(array[0]);

	cout<<"二叉树顺序: "<<endl;
	for(int i=0;i<k;i++)
	{
		cout<<array[i]<<" ";
		A.create_bstree(array[i]);
	}   cout<<endl;

	printTree(A.root); // 是使用根节点来打印
	return 0;
}


在学习二叉树的时候,我最关注的是这个数据结构是怎么存在的,数据按照规则存放在哪。

按照我的理解,数据本身无序,所以建立数据结构,需要给数包装。这个包装就是Tree结构体。

包装以后的数据,带有其他的参数变量(指针居多),用于支撑这个结构。(方便后续的数据处理)

在内存中,把数据包装,用指针建立两两间关系,数据结构就好了。


tip:

其实,显示函数的优劣很重要。但是写不出来好的也没关系。我们可以在debug下设置断点,一步步查看root里面数据的变化,就可以看到数据的层次。


二、寻找函数

寻找函数(声明部分)

// * 二叉查找树的类
class BTree
{
public:
	tree* root;
	BTree(){ root = NULL; }
	void create_bstree(int);
	void printTree(tree*); // 可以只给出类型
	int getDepth(tree*,int);
	void setDepth(tree*);
	tree* find(tree* dtree, int x);
private:
	int depth;
};


寻找函数(实现部分)

// * 给元素赋值深度(可以放在create_bstree中吗?思路就不清晰了。)
void BTree::setDepth(tree* Dtree)
{
	if(Dtree == NULL)
		cout<<"树为空!"<<endl;

	else
	{
		if(Dtree->left != NULL ) // 实际上函数是利用父节点来设置子节点的深度
		{
			Dtree->left->depth = Dtree->depth + 1;
			setDepth(Dtree->left);
		}
		if(Dtree->right != NULL )
		{
			Dtree->right->depth = Dtree->depth + 1;
			setDepth(Dtree->right);
		}
	}
}

// * 查询元素,返回其父(子树的root)
// 逻辑解释:最大的困惑是if(dtree->key == x && dtree != NULL)似乎是更合适的条件,相等,而且非空。
//           其实不然。相等自然没错,但是“&& 非空”的条件,想想当迭代一直到树叶的时候会怎么样?
//           条件不成立,去执行 dtree->key,这时候就会发生内存读取错误。因为这时候的dtree是NULL!
/*
tree* BTree::find(tree* dtree, int x)
{
	if(dtree->key == x || dtree == NULL) 
		return dtree;
	else if(dtree->key < x) //往右寻找
		return find(dtree->right,x);
	else // 往左寻找
		return find(dtree->left,x);
}
*/

// 改进后的,增加外来元素的判断,外来元素返回NULL
tree* BTree::find(tree* dtree, int x)
{
	if(dtree->key == x) 
		return dtree;
	else if(dtree->key < x) //往右寻找
	{
		if(dtree->right != NULL)
			return find(dtree->right,x);
		else
			return NULL;
	}
	else // 往左寻找
	{
		if(dtree->left != NULL)
			return find(dtree->left,x);
		else
			return NULL;
	}

}


// * 查询深度(要先执行setDepth() )
int BTree::getDepth(tree* dtree, int x)
{
	tree* result = BTree::find(dtree,x);
	if(result != NULL)
		return result->depth;
	else
		return -1; // 没有这个元素
}

调用示例

	cout<<"100的深度是"<<A.getDepth(A.root,55)<<endl;

同样可以在

三、三种遍历

可以参看连接2

1.先序遍历

2.中序遍历

3.后序遍历





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值