c#使用数组实现二叉查找树
2014-11-08 21:08
253 查看
原创性申明:
本文地址是/article/1515235.html 转载请注明出处。作者联系邮箱 zhujunxxxxx@163.com二叉排序树
(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。它或者是一棵空树;或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
树的储方案:
用数组来实现二叉树,树上的元素存放位置在数组中是固定的---如果树的i位置(从1开始按层编号)有元素,就放在数组的i号位置,没有元素,数组对应的位置就空着。i的左右子树的编号为2i和2i+1。
1,实例变量,容量动态扩展,以及构造方法:
/// <summary> /// 数组存储树的结构(还有一种是Node) /// </summary> private int[] data;//从1开始存储数据 /// <summary> /// 树的长度 /// </summary> private int len; /// <summary> /// 删除节点时用的一个临时的数据结构 /// </summary> private List<int> tmpList; public Tree() { //先初始化一个1w大小的数组 this.data = new int[100]; tmpList = new List<int>(); len = 0; }
2,树的插入
数组实现插入其实跟链式思想还是一样,往下找插入节点就是往下找插入的下标,下标的关系已经在前面说过,要注意的是数组容量可能不够,需要扩展容量/// <summary> /// 把节点插入树 /// </summary> public void Insert(int key) { if (len == 0) { data[1] = key; len++; } else { int index = 1; while (index <data.Length) { if (key < data[index]) { //拓展数组 if (LeftChild(index) >= data.Length) Expand(); //判断这个节点是否为空 if (data[LeftChild(index)] == 0) { data[LeftChild(index)] = key; len++; break; } else { index = LeftChild(index); } } else { //拓展数组 if (RightChild(index) >= data.Length) Expand(); //判断这个节点是否为空 if (data[RightChild(index)] == 0) { data[RightChild(index)] = key; len++; break; } else { index = RightChild(index); } } } } }
3,树的删除
当某个结点被删后,它的子树上的全部结点的下标都要调整,而且这个调整顺序还得从上网下调,否则下面的节点的可能覆盖上面的,没有想到什么好的办法,最后只有用了一个消耗最大的笨方法---将被删结点置为null后,前序遍历树(或者后序,不能中序),
将前序序列依次重新插入建树。相当于删除节点后,把剩下结点取出来重新建树
/// <summary> /// 删除树的节点 /// </summary> public int Delete(int key) { int value=-1; int index = Search(key); if (index != -1) { value=data[index]; Remove(index); } return value; } /// <summary> /// 移除一个节点,并重新构造树 /// </summary> /// <param name="index"></param> private void Remove(int index) { //设置要删除的值为0 data[index] = 0; //删除指定下标处的元素,并得到删除后的树(调整位置) List<int> it = PreInorderList();//得到前序遍历的迭代器 for (int i = 1; i < data.Length; i++)//将树清空 data[i] = 0; //把树给清空,长度也变为0 len = 0; foreach (int item in it) { Insert(item); } }
4,树的前序遍历
/// <summary> /// 先序遍历 /// </summary> public void PreOrder(int i) { if (i >= data.Length) return; if (data[i] != 0) { tmpList.Add(data[i]); } PreOrder(LeftChild(i)); PreOrder(RightChild(i)); }
5,树的中序遍历
/// <summary> /// 中序遍历 /// </summary> /// <param name="i"></param> public void InOrder(int i) { if (i >=data.Length) return; InOrder(LeftChild(i)); if (data[i] != 0) { Console.Write(data[i] + " "); } InOrder(RightChild(i)); }
6,树的后续遍历
/// <summary> /// 后续遍历 /// </summary> /// <param name="i"></param> public void PostOrder(int i) { if (i >= data.Length) return; PostOrder(LeftChild(i)); PostOrder(RightChild(i)); if (data[i] != 0) { Console.Write(data[i] + " "); } }
使用实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Other
{
/// <summary>
/// 二叉排序树(Binary Sort Tree)
/// 二叉查找树(Binary Search Tree)
/// </summary>
public class Tree
{
/// <summary> /// 数组存储树的结构(还有一种是Node) /// </summary> private int[] data;//从1开始存储数据 /// <summary> /// 树的长度 /// </summary> private int len; /// <summary> /// 删除节点时用的一个临时的数据结构 /// </summary> private List<int> tmpList; public Tree() { //先初始化一个1w大小的数组 this.data = new int[100]; tmpList = new List<int>(); len = 0; }
/// <summary> /// 把节点插入树 /// </summary> public void Insert(int key) { if (len == 0) { data[1] = key; len++; } else { int index = 1; while (index <data.Length) { if (key < data[index]) { //拓展数组 if (LeftChild(index) >= data.Length) Expand(); //判断这个节点是否为空 if (data[LeftChild(index)] == 0) { data[LeftChild(index)] = key; len++; break; } else { index = LeftChild(index); } } else { //拓展数组 if (RightChild(index) >= data.Length) Expand(); //判断这个节点是否为空 if (data[RightChild(index)] == 0) { data[RightChild(index)] = key; len++; break; } else { index = RightChild(index); } } } } }
/// <summary> /// 删除树的节点 /// </summary> public int Delete(int key) { int value=-1; int index = Search(key); if (index != -1) { value=data[index]; Remove(index); } return value; } /// <summary> /// 移除一个节点,并重新构造树 /// </summary> /// <param name="index"></param> private void Remove(int index) { //设置要删除的值为0 data[index] = 0; //删除指定下标处的元素,并得到删除后的树(调整位置) List<int> it = PreInorderList();//得到前序遍历的迭代器 for (int i = 1; i < data.Length; i++)//将树清空 data[i] = 0; //把树给清空,长度也变为0 len = 0; foreach (int item in it) { Insert(item); } }
/// <summary>
/// 获取先序遍历的序列
/// </summary>
/// <returns></returns>
private List<int> PreInorderList()
{
//生成前序序列
PreOrder(1);
List<int> tmp = tmpList;
//重新把这个初始为空
tmpList = new List<int>();
return tmp;
}
/// <summary>
/// 获取左孩子
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
private int LeftChild(int i)
{
return i * 2;
}
/// <summary>
/// 获取右孩子
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
private int RightChild(int i)
{
return i * 2+1;
}
/// <summary>
/// 当容量不够的时候拓展数组的大小
/// </summary>
private void Expand()
{
//一次扩大两倍
int[] larger = new int[data.Length * 2];
for (int i = 1; i < data.Length; i++)
{
larger[i] = data[i];
}
data = larger;
}
/// <summary>
/// 查找树节点
/// </summary>
public int Search(int key)
{
int index = 1;
while (index < data.Length && data[index] != 0)
{
if (data[index] == key)
return index;
else if (key < data[index])
{
index = LeftChild(index);
}
else
{
index = RightChild(index);
}
}
return -1;
}
/// <summary>
/// 输出树的结构
/// </summary>
public override string ToString()
{
return null;
}
/// <summary> /// 先序遍历 /// </summary> public void PreOrder(int i) { if (i >= data.Length) return; if (data[i] != 0) { tmpList.Add(data[i]); } PreOrder(LeftChild(i)); PreOrder(RightChild(i)); }
/// <summary> /// 中序遍历 /// </summary> /// <param name="i"></param> public void InOrder(int i) { if (i >=data.Length) return; InOrder(LeftChild(i)); if (data[i] != 0) { Console.Write(data[i] + " "); } InOrder(RightChild(i)); }
/// <summary> /// 后续遍历 /// </summary> /// <param name="i"></param> public void PostOrder(int i) { if (i >= data.Length) return; PostOrder(LeftChild(i)); PostOrder(RightChild(i)); if (data[i] != 0) { Console.Write(data[i] + " "); } }
}
}
static void Main(string[] args) { Tree t = new Tree(); t.Insert(50); t.Insert(20); t.Insert(60); t.Insert(15); t.Insert(30); t.Insert(70); //从第一个位置开始 t.InOrder(1); Console.WriteLine(); t.Delete(20); t.InOrder(1); }
相关文章推荐
- c# 使用linq查询子句方式实现 字符串数组统计操作
- C#使用泛型数组简单实现一个列表List
- unity3d 中使用C#脚本 实现数组的倒序存储并输出
- C# :自己动手实现:使用数组的方式实现List
- C#字符串数组排序 C#排序算法大全 C#字符串比较方法 一个.NET通用JSON解析/构建类的实现(c#) C#处理Json文件 asp.net使用Jquery+iframe传值问题
- C#中使用XML——实现DOM
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分
- 如何在C# 中使用WMI 实现远程查询和共享
- 如何在C# 中使用WMI 实现远程查询和共享
- 使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分
- 使用C#实现阿拉伯数字到大写中文的转换-第二种方法
- 使用未公开关键字在 C# 中导入外部 printf 等参数数量可变函数 [2] C# 实现
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(二)----使用方法
- 使用C#代码实现增加用户帐号
- 使用C#代码实现增加用户帐号
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(二)----使用方法
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(二)----使用方法
- 在C#中使用COM+实现事务控制
- [导入]如何使用 C# .NET 在 ASP.NET 应用程序中实现基于窗体的身份验证