原創性申明:
本文地址是http://blog.csdn.net/zhujunxxxxx/article/details/40925687 轉載請註明出處。作者聯繫郵箱 [email protected]
二叉排序樹
(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);
}