從新整理數據結構與算法(c#)—— 平衡二叉樹[二十三]

前言

由於有些樹是這樣子的:node

這樣子的樹有個壞處就是查詢效率低,由於左邊只有一層,而右邊有3層,這就說明若是查找一個數字大於根元素的數字,那麼查詢判斷就更多。ide

解決方法就是下降兩邊的層數差距:測試

變成這樣。this

那麼如何這樣作呢?3d

若是右邊比左邊層次大於1,進行左旋轉規格:code

若是左邊比右邊層次大於1,進行右旋轉:blog

爲何是這樣處理呢?排序

我拿左旋轉來講:get

左邊是1,右邊是3,那麼須要右邊的給一層給左邊。string

這時候就是6做爲根節點,6做爲根節點,自己呢,就是一顆二叉樹。

這時候呢,6大於4,因此4在6的右邊,而6的左節點確定大於4(原理的根節點)小於6,因此做爲4的左節點代替,4也就成了6的左節點。

右旋轉同理。

旋轉會出現的問題

就是這樣經過右旋轉以後,可能達不到目標。

看上面這張圖,右旋轉後仍是不平衡,爲何會這樣呢?緣由是這樣的,咱們來看下本質問題,右旋轉幹了什麼?右旋轉實際上是從新分配元素的過程。

看我這種圖紅色部分,實際上是將紅色部門分給了右邊,這時候會存在元素個數差別過大的問題。

那麼這時候該怎麼辦呢?

要讓紅框部分進行左旋轉才行,那麼看代碼吧。

正文

節點模型:

public class Node
{
	public Node left;

	public Node right;

	int value;

	public int Value { get => value; set => this.value = value; }

	public Node(int value)
	{
		this.Value = value;
	}
	//中序排序
	public void infixOrder()
	{
		if (this.left != null)
		{
			this.left.infixOrder();
		}
		Console.WriteLine(this);
		if (this.right != null)
		{
			this.right.infixOrder();
		}
	}
	//左子樹高度
	public int leftHeight() {
		if (left == null)
		{
			return 0;
		}
		return this.left.height();
	}
	//右子樹高度
	public int rightHeight() {
		if (right == null)
		{
			return 0;
		}
		return this.right.height();
	}
	//計算高度
	public int height()
	{
		return Math.Max(left==null?0:this.left.height(),right==null?0:this.right.height())+1;
	}
	//進行左旋轉
	private void leftRotate()
	{
		Node newNode = new Node(value);
		newNode.left = left;
		newNode.right = right.left;
		//將右節點變成根節點
		value =right.value;
		//原先右節點被拋棄
		right=right.right;
		//左節點設置爲
		left = newNode;
	}
	//進行右旋轉
	private void rightRotate()
	{
		Node newNode = new Node(value);
		newNode.left = left.right;
		newNode.right = right;
		value = this.left.value;
		left = left.left;
		right = newNode;
	}
	public override string ToString()
	{
		return Value.ToString();
	}
	//增長元素
	public void addNode(Node node)
	{
		if (node.Value < this.Value)
		{
			if (this.left == null)
			{
				this.left = node;
			}
			else
			{
				this.left.addNode(node);
			}
		}
		else {
			if (this.right == null)
			{
				this.right = node;
			}else {
				this.right.addNode(node);
			}
		}
		if (rightHeight() > leftHeight() + 1)
		{
			if (right.leftHeight() > right.rightHeight())
			{
				right.rightRotate();

			}
			this.leftRotate();
		}
		else if (leftHeight() > rightHeight() + 1)
		{
			if (left.rightHeight() > left.leftHeight())
			{
				left.leftRotate();
			}
			this.rightRotate();
		}
	}
	public Node searchParentNode(int value)
	{
		if ((this.left != null && this.left.value == value || (this.right != null && this.right.value == value)))
		{
			return this;
		}
		else
		{
			if (this.value < value && this.left != null)
			{
				return this.left.searchParentNode(value);
			}
			else if (this.value >= value && this.right != null)
			{
				return this.right.searchParentNode(value);
			}
			else
			{
				return null;
			}
		}
	}
	//查找元素
	public Node searchNode(int value)
	{
		if (this.Value == value)
		{
			return this;
		}
		if (this.Value > value)
		{
			if (this.left != null)
			{
				return this.right.searchNode(value);
			}
			else
			{
				return null;
			}
		}
		else
		{
			if (this.left != null)
			{
				return this.left.searchNode(value);
			}
			else
			{
				return null;
			}
		}
	}
}

樹模型:

public class BinarySortTree
{
	//根節點
	Node root;

	internal Node Root { get => root; set => root = value; }

	public BinarySortTree(Node root)
	{
		this.Root = root;
	}

	public BinarySortTree() : this(null)
	{

	}

	public void add(Node node)
	{
		if (Root == null)
		{
			Root = node;
		}
		else
		{
			this.Root.addNode(node);
		}
	}

	public void infixOrder()
	{
		if (Root == null)
		{
			Console.WriteLine("root 爲空");
		}
		else
		{
			Root.infixOrder();
		}
	}

	public Node searchNode(int value)
	{
		if (Root==null)
		{
			Console.WriteLine("root 爲空");
		}
		return Root.searchNode(value);
	}

	public int delRightTreeMin(Node node)
	{
		Node tagert = node;
		while (tagert.left!=null)
		{
			tagert = tagert.left;
		}
		delNode(tagert.Value);
		return tagert.Value;
	}

	public Node searchParentNode(int value)
	{
		if (Root != null)
		{
			return Root.searchParentNode(value);
		}
		return null;
	}

	public void delNode(int value)
	{
		if (Root == null)
		{
			return;
		}
		Node node=searchNode(value);
		if (node == null)
		{
			return;
		}
		if (node.Value == Root.Value)
		{
			Root = null;
			return;
		}
		Node parent = searchParentNode(value);
		if (node.left == null && node.right == null)
		{
			if (parent.left.Value == value)
			{
				parent.left = null;
			}
			else
			{
				parent.right = null;
			}
		}
		else if (node.left != null && node.right != null)
		{
			 //刪除左邊最大值或者右邊最小值,而後修改值爲刪除的值
			 parent.right.Value=delRightTreeMin(node.right);
		}
		else
		{
			if (node.left != null)
			{
				if (parent.left.Value == value)
				{
					parent.left = node.left;
				}
				else
				{
					parent.right = node.left;
				}
			}
			else {
				if (parent.left.Value == value)
				{
					parent.left = node.right;
				}
				else
				{
					parent.right = node.right;
				}
			}
		}
	}
}

測試代碼:

static void Main(string[] args)
{
	int[] arr = { 10, 11, 7, 6, 8, 9 };
	BinarySortTree binarySortTree = new BinarySortTree();
	//循環的添加結點到二叉排序樹
	for (int i = 0; i < arr.Length; i++)
	{
		binarySortTree.add(new Node(arr[i]));
	}
	//中序遍歷後的數據
	Console.WriteLine("樹的高度=" + binarySortTree.Root.height()); //3
	Console.WriteLine("樹的左子樹高度=" + binarySortTree.Root.leftHeight()); // 2
	Console.WriteLine("樹的右子樹高度=" + binarySortTree.Root.rightHeight()); // 2
	Console.WriteLine("當前的根結點=" + binarySortTree.Root);//8
	Console.Read();
}

結果:

相關文章
相關標籤/搜索