代碼實現(自己學習過程的產物,僅供自己玩)
/// <summary> /// 二叉查找樹 /// </summary> public class BinarySearchTree { #region 構造函數 public BinarySearchTree(BinarySearchTreeNode root) { this.Root = root; } public BinarySearchTree(long[] nodeValues) { if (nodeValues == null || nodeValues.Length == 0) return; this.Root = new BinarySearchTreeNode() { Value = nodeValues[0] }; for (int i = 1; i < nodeValues.Length; i++) { AddNode(nodeValues[i]); } } #endregion #region 屬性區域 public BinarySearchTreeNode Root { get; set; } #endregion #region 函數區域 /// <summary> /// 獲取具有最大值的節點 /// </summary> /// <returns>具有最大值的節點</returns> public BinarySearchTreeNode GetMaxNode() { return GetMaxNode(Root); } /// <summary> /// 獲取具有最大值的節點 /// </summary> /// <returns>具有最大值的節點</returns> public BinarySearchTreeNode GetMaxNode(BinarySearchTreeNode root) { BinarySearchTreeNode maxNode = root; BinarySearchTreeNode rightNode = root.Right; while (rightNode != null) { maxNode = rightNode; rightNode = rightNode.Right; } return maxNode; } /// <summary> /// 獲取二叉查找樹的最大值 /// </summary> /// <returns>二叉查找樹的最大值</returns> public long GetMax() { BinarySearchTreeNode node = GetMaxNode(Root); if (node == null) throw new Exception("最大值不存在"); return node.Value; } /// <summary> /// 獲取具有最小值的節點 /// </summary> /// <returns>具有最小值的節點</returns> public BinarySearchTreeNode GetMinNode() { return GetMinNode(Root); } /// <summary> /// 獲取具有最小值的節點 /// </summary> /// <returns>具有最小值的節點</returns> public BinarySearchTreeNode GetMinNode(BinarySearchTreeNode root) { BinarySearchTreeNode minNode = root; BinarySearchTreeNode leftNode = root.Left; while (leftNode != null) { minNode = leftNode; leftNode = minNode.Left; } return minNode; } /// <summary> /// 獲取二叉查找樹的最小值 /// </summary> /// <returns>二叉查找樹的最小值</returns> public long GetMin() { BinarySearchTreeNode node = GetMinNode(); if (node == null) throw new Exception("最小值不存在"); return node.Value; } /// <summary> /// 獲取指定節點的前驅節點 /// </summary> /// <param name="node">要獲取前驅節點的節點</param> /// <returns>指定節點的前驅節點</returns> public BinarySearchTreeNode GetPredecessor(BinarySearchTreeNode node) { if (node == null) return null; // 左子樹不爲空,則節點的前驅爲左子樹的最大值節點 if (node.Left != null) { return GetMaxNode(node.Left); } else { // 左子樹爲空,則向上查找,直到某個是其父節點的左兒子的節點爲止(反過來當前節點是要求節點的後繼節點,可以想象下位置,右子樹最小節點) BinarySearchTreeNode parent = node.Parent; while (parent != null && parent.Left == node) { node = parent; parent = parent.Parent; } return parent; } } /// <summary> /// 獲取指定節點的後繼節點 /// </summary> /// <param name="node">要獲取後繼節點的節點</param> /// <returns>指定節點的</returns> public BinarySearchTreeNode GetSuccessor(BinarySearchTreeNode node) { if (node == null) return null; // 右子樹不爲空,則節點的後繼爲右子樹的最小值節點 if (node.Right != null) { return GetMinNode(node.Right); } else { // 右子樹爲空,則向上查找,直到某個是其父節點的右兒子的節點爲止(反過來當前節點是要求節點的前驅節點,可以想象下位置,左子樹最大節點) BinarySearchTreeNode parent = node.Parent; while (parent != null && parent.Right == node) { node = parent; parent = parent.Parent; } return parent; } } /// <summary> /// 搜索具有指定值的節點 /// </summary> /// <param name="value">指定值</param> /// <returns>具有指定值的節點</returns> public BinarySearchTreeNode Search(long value) { return Search(Root, value); } /// <summary> /// 搜索具有指定值的節點 /// </summary> /// <param name="value">指定值</param> /// <returns>具有指定值的節點</returns> private BinarySearchTreeNode Search(BinarySearchTreeNode parent, long value) { if (parent == null) return null; if (parent.Value == value) return parent; BinarySearchTreeNode searchedNode = null; if (value < parent.Value) { // 向左搜索 searchedNode = Search(parent.Left, value); } if (value > parent.Value) { // 向右搜索 searchedNode = Search(parent.Right, value); } return searchedNode; } /// <summary> /// 添加一個節點到二叉查找樹(並保持二叉查找樹的特性) /// </summary> /// <param name="node">要添加的節點</param> public void AddNode(long node) { if (Root.Value >= node) { // 向左子樹添加 if (Root.Left == null) { // 添加 Root.Left = new BinarySearchTreeNode() { Parent = Root, Left = null, Right = null, Value = node }; return; } AddNode(node, Root.Left); } if (Root.Value < node) { // 向右子樹添加 if (Root.Right == null) { // 添加 Root.Right = new BinarySearchTreeNode() { Parent = Root, Left = null, Right = null, Value = node }; return; } AddNode(node, Root.Right); } } /// <summary> /// 向指定的子樹中添加節點 /// </summary> /// <param name="node">要添加節點</param> /// <param name="parent">子樹</param> private void AddNode(long node, BinarySearchTreeNode parent) { if (parent.Value >= node) { // 向左子樹添加 if (parent.Left == null) { // 添加 parent.Left = new BinarySearchTreeNode() { Parent = parent, Left = null, Right = null, Value = node }; return; } AddNode(node, parent.Left); } if (parent.Value < node) { // 向右子樹添加 if (parent.Right == null) { // 添加 parent.Right = new BinarySearchTreeNode() { Parent = parent, Left = null, Right = null, Value = node }; return; } AddNode(node, parent.Right); } } /// <summary> /// 刪除指定的節點(並保持二叉查找樹的特性) /// </summary> /// <param name="node">要刪除的節點</param> public void DeleteNode(BinarySearchTreeNode node) { if (node == null) throw new ArgumentNullException("參數node爲空"); if (node.Left == null && node.Right == null) { // 當前節點爲葉子節點,則直接刪除 BinarySearchTreeNode parent = node.Parent; if (parent.Value >= node.Value) { parent.Left = null; } else { parent.Right = null; } } if ((node.Left != null && node.Right == null) || (node.Left == null && node.Right != null)) { // 只有一個子節點的節點,則直接追加該子節點 BinarySearchTreeNode parent = node.Parent; if (parent.Value >= node.Value) { parent.Left = node.Left == null ? node.Right : node.Left; parent.Left.Parent = parent; } else { parent.Right = node.Left == null ? node.Right : node.Left; parent.Right.Parent = parent; } } if (node.Left != null && node.Right != null) { // 備份當前節點 BinarySearchTreeNode copyNode = node.Clone() as BinarySearchTreeNode; // 刪除後繼節點 BinarySearchTreeNode postNode = GetSuccessor(node); DeleteNode(postNode); // 用後繼節點代替當前節點 postNode.Left = node.Left; postNode.Right = node.Right; postNode.Parent = node.Parent; postNode.Tag = node.Tag; postNode.Value = node.Value; } } #endregion } /// <summary> /// 二叉查找樹節點 /// </summary> public class BinarySearchTreeNode : ICloneable { #region 構造函數 public BinarySearchTreeNode() { } public BinarySearchTreeNode(BinarySearchTreeNode parent, BinarySearchTreeNode left, BinarySearchTreeNode right, long value, object tag) { this.Parent = parent; this.Left = left; this.Right = right; this.Value = value; this.Tag = tag; } #endregion #region 屬性節點 /// <summary> /// 父節點 /// </summary> public BinarySearchTreeNode Parent { get; set; } /// <summary> /// 左兒子 /// </summary> public BinarySearchTreeNode Left { get; set; } /// <summary> /// 右兒子 /// </summary> public BinarySearchTreeNode Right { get; set; } /// <summary> /// 節點值 /// </summary> public long Value { get; set; } /// <summary> /// 存儲其他值 /// </summary> public object Tag { get; set; } #endregion #region ICloneable 成員 public object Clone() { return new BinarySearchTreeNode() { Left = this.Left, Right = this.Right, Parent = this.Parent, Tag = this.Tag, Value = this.Value }; } #endregion }
強化學習概覽 This overview is largely based on this article: https://medium.com/@SmartLabAI/reinforcement-learning-algorithms
插入排序法 1.工作原理(算法思路) 新建一個指針,指針左邊的所有元素都是有序的。但是他們的位置並不是最終位置,一個指針從左向右掃描,若指針所在處的元素比左邊元素小,則將該元素向前浮動至適當位置,使指針左側元素仍然保持有序。當指針掃描到整
分治基本思想影響算法複雜度的因素經典案例1 二分檢索設計思想僞碼2 二分歸併設計思想僞碼3 漢諾塔設計思想僞碼4 快速排序設計思想僞碼實例5 快速傅里葉變換(信號平滑處理)問題描述設計&分析減少子問題個數案例:大數相乘設計思想參考
XGBoost可以用來分類,迴歸,排序。 支持多種語言:C++, Python, R, Java, Scala, Julia。 安裝 參考https://xgboost.readthedocs.io/en/latest/buil
NDCG(Normalized Discounted Cumulative Gain): 維基百科寫的很清楚。 注意理解這四個詞。 Discounted:順序影響指標。 Normalized:消除文檔個數對指標的影響。
商品關聯分析 關聯 relevance: 主要用在互聯網的內容和文檔上,比如搜索引擎算法文檔中之間的關聯性。 association: 用在實際的事物之上,比如電子商務網站上的商品之間的關聯度。 支持度(support):數據集中
簡單記錄一下關於仿真優化的一些知識點和思考。主要基於:Handbook of Simulation Optimization, Michael Fu Table of Contents Overview Discrete Optimiza
點這個: https://towardsdatascience.com/a-road-map-for-deep-learning-b9aee0b2919f
Currently learning stochastic optimization (SO) theory, I will note important content here. Some book references ar
Reading notes of the paper "Distributed Optimization and Statistical Learning via ADMM" by Boyd, Parikh, Chu, Peleato a
Source:http://www.seas.ucla.edu/~vandenbe/ee236c.html Introduction Outline First-order algorithms Decomposition and s
Overview of gradient descent algorithms An overview of gradient descent optimization algorithms Gradient descent is
function TreeNode(val) { this.val = val; this.left = this.right = null; } 解一:遞歸 先判斷樹結構是否爲null,如果是null,直接
雖然網上已經很多這種排序算法了,但是爲了讓自己更熟悉一點(也順便寫篇博客),所以準備把基本的那幾種算法原理及代碼重新寫一遍 今天先來冒泡算法吧,冒泡算法的基本原理就是通過不斷的比較兩個相鄰元素的大小,如果前一個比後一個大,則交換兩個元素的