树(数据结构的一种 )
树
什么是树的层次?
最大层是树的深度
什么是有序树和无序树?
树的错误案例
1,树只有一个根节点
2,子树之间是不相交的
3,一个结点不能有两个父结点
树的存储结构
我们使用链式存储来表示树。
二叉树性质
二叉树存储结构
一般的树来说是一对多的关系,使用顺序结构存储起来比较困难,但是二叉树是一种特殊的树,每个结点最多有两个子节点,并且子节点有左右之分,并且兄弟,父亲,孩子可以很方便的通过编号得到,所以我们使用顺序存储结构使用二叉树的存储。
二叉树 - 二叉链表存储
二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域,我们称这样的链表为二叉链表。
二叉树的遍历
代码实现
建立一个二叉树类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 二叉树_顺序结构存储
{
//如果一个结点是空的话,那么这个结点所在的数组位置,设置为-1
class BiTree<T>
{
private T[] data;
private int count = 0;
public BiTree(int capacity)//这个参数是当前二叉树的容量,容量是最多可以存储的数据个数,数量count代表当前保存了多少个数据
{
data = new T[capacity];
}
public bool Add(T item)
{
if (count >= data.Length)
return false;
data[count] = item;
count++;
return true;
}
//前序遍历
public void FirstTraversal()
{
FirstTraversal(0);
}
private void FirstTraversal(int index)
{
if (index >= count) return;
//得到要遍历的这个结点的编号
int number = index + 1;
if (data[index].Equals(-1)) return;
Console.Write(data[index] + " ");
//得到左子结点的编号
int leftNumber = number * 2;
int rightNumber = number * 2 + 1;
FirstTraversal(leftNumber - 1);
FirstTraversal(rightNumber - 1);
}
//中序遍历
public void MiddleTraversal()
{
MiddleTraversal(0);
}
private void MiddleTraversal(int index)
{
if (index >= count) return;
//得到要遍历的这个结点的编号
int number = index + 1;
if (data[index].Equals(-1)) return;
int leftNumber = number * 2;
int rightNumber = number * 2 + 1;
MiddleTraversal(leftNumber - 1);
Console.Write(data[index] + " ");
MiddleTraversal(rightNumber - 1);
}
//后序遍历
public void LastTraversal()
{
LastTraversal(0);
}
private void LastTraversal(int index)
{
if (index >= count) return;
//得到要遍历的这个结点的编号
int number = index + 1;
if (data[index].Equals(-1)) return;
int leftNumber = number * 2;
int rightNumber = number * 2 + 1;
LastTraversal(leftNumber - 1);
LastTraversal(rightNumber - 1);
Console.Write(data[index] + " ");
}
public void LayerTraversal()
{
for (int i = 0; i < count; i++)
{
if (data[i].Equals(-1)) continue;
Console.Write(data[i] + " ");
}
Console.WriteLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 二叉树_顺序结构存储
{
class Program
{
static void Main(string[] args)
{
char[] data = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };//这个是我们要存储的数据
BiTree<char> tree = new BiTree<char>(10);
for (int i = 0; i < data.Length; i++)
{
tree.Add(data[i]);
}
tree.FirstTraversal();
Console.WriteLine();
tree.MiddleTraversal();
Console.WriteLine();
tree.LastTraversal();
Console.WriteLine();
tree.LayerTraversal();
Console.ReadKey();
}
}
}
二叉排序树
二叉排序树,又称为二叉查找树。它或者是一棵空树,或者是具有下列性质的二叉树。
若它的左子树不为空,则左子树上所有的结点的值均小于根结构的值;
若它的右子树不为空,则右字数上所有结点的值均大于它的根结点的值;
它的左右子树也分别为二叉排序树。
1,排序方便
2,方便查找
3,方便插入和删除
4,通过中序遍历就能进行排序
二叉排序树 删除操作
这种情况是添加左子树最大的结点或者右子树最小的结点到47
二叉排序树的代码实现
一个是结点类的定义BSNode
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 二叉排序树_链式存储
{
class BSNode
{
public BSNode LeftChild { get; set; }
public BSNode RightChild { get; set; }
public BSNode Parent { get; set; }
public int Data { get; set; }
public BSNode()
{
}
public BSNode(int item)
{
this.Data = item;
}
}
}
一个是树类的定义 BSTree
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 二叉排序树_链式存储
{
class BSTree
{
BSNode root = null;
//添加数据
public void Add(int item)
{
BSNode newNode = new BSNode(item);
if (root == null)
root = newNode;
else
{
BSNode temp = root;
while (true)
{
if (item >= temp.Data)
{
//放在temp的右边
if(temp.RightChild == null)
{
temp.RightChild = newNode;
newNode.Parent = temp;
break;
}
else
{
temp = temp.RightChild;
}
}
else
{
//放在temp的左边
if (temp.LeftChild == null)
{
temp.LeftChild = newNode;
newNode.Parent = temp;
break;
}
else
{
temp = temp.LeftChild;
}
}
}
}
}
//排序,其实就是中序遍历
public void MiddleTraversal()
{
MiddleTraversal(root);
}
private void MiddleTraversal(BSNode node)
{
if (node == null) return;
MiddleTraversal(node.LeftChild);
Console.Write(node.Data + " ");
MiddleTraversal(node.RightChild);
}
//查找
public bool Find(int item)
{
//return Find(item, root);
BSNode temp = root;
while (true)
{
if (temp == null) return false;
if (temp.Data == item) return true;
if (item > temp.Data)
temp = temp.RightChild;
else
temp = temp.LeftChild;
}
}
private bool Find(int item,BSNode node)
{
if (node == null) return false;
if (node.Data == item) return true;
else
{
//if (Find(item, node.LeftChild))
// return true;
//if (Find(item, node.RightChild))
// return true;
if (item > node.Data)
return Find(item, node.RightChild);
else
return Find(item, node.LeftChild);
}
}
public bool Delete(int item)
{
BSNode temp = root;
while (true)
{
if (temp == null) return false;
if (temp.Data == item) Delete(temp);
if (item > temp.Data)
temp = temp.RightChild;
else
temp = temp.LeftChild;
}
}
public void Delete(BSNode node)
{
//如果是叶子结点
if(node.LeftChild == null && node.RightChild == null)
{
if(node.Parent == null)//删除的是根结点
{
root = null;
}
if(node.Parent.LeftChild == node)
node.Parent.LeftChild = null;
else if (node.Parent.RightChild == node)
node.Parent.RightChild = null;
}
if(node.LeftChild == null && node.RightChild != null)
{
//将右子树的值赋给要删除的结点,然后删除右子树
node.Data = node.RightChild.Data;
node.RightChild = null;
return;
}
if (node.LeftChild != null && node.RightChild == null)
{
//将左子树的值赋给要删除的结点,然后删除左子树
node.Data = node.LeftChild.Data;
node.LeftChild = null;
return;
}
if (node.LeftChild != null && node.RightChild != null)
{
//找右子树中值最小的结点
BSNode temp = node.RightChild;
while(true)
{
if(temp.LeftChild != null)
{
temp = temp.LeftChild;
}
else
{
break;
}
}
node.Data = temp.Data;
Delete(temp);
}
}
}
}
代码验证
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 二叉排序树_链式存储
{
class Program
{
static void Main(string[] args)
{
BSTree tree = new BSTree();
int[] data = { 62, 58, 88, 47, 73, 99, 35, 51, 93, 37 };
foreach (int t in data)
{
tree.Add(t);
}
tree.MiddleTraversal();
Console.WriteLine();
Console.WriteLine(tree.Find(91));
Console.WriteLine(tree.Find(99));
tree.Delete(51);
tree.MiddleTraversal();
Console.ReadKey();
}
}
}