Django學習日記-06新url多對多表新增 編輯操作
目錄
二叉樹
二叉樹是一種非常重要的資料結構,非常多其他資料結構都是基於二叉樹的基礎演變而來的。對於二叉樹,有深度遍歷和廣度遍歷,深度遍歷有前序、中序以及後序三種遍歷方法,廣度遍歷即我們尋常所說的層次遍歷。由於樹的定義本身就是遞迴定義,因此採用遞迴的方法去實現樹的三種遍歷不僅easy理解並且程式碼非常簡潔,而對於廣度遍歷來說,須要其他資料結構的支撐。比方堆了。所以。對於一段程式碼來說,可讀性有時候要比程式碼本身的效率要重要的多。
遍歷路徑
前序遍歷:根->左->右
中序遍歷:左->根->右(最重要)
後續遍歷:左->右->根
層次遍歷:根->左->右
樹遍歷框架
所有樹的遍歷均可以套用樹遍歷框架
void traverse(TreeNode root) {
// 前序遍歷
traverse(root.left)
// 中序遍歷
traverse(root.right)
// 後序遍歷
}
例子1(二叉搜尋樹轉換為單向連結串列)
二叉樹資料結構TreeNode可用來表示單向連結串列(其中left置空,right為下一個連結串列節點)。實現一個方法,把二叉搜尋樹轉換為單向連結串列,要求值的順序保持不變,轉換操作應是原址的,也就是在原始的二叉搜尋樹上直接修改。
返回轉換後的單向連結串列的頭節點。
示例:
輸入: [4,2,5,1,3,null,6,0]
輸出: [0,null,1,null,2,null,3,null,4,null,5,null,6]
//上級節點 TreeNode preNode; //頭節點 TreeNode headNode; public TreeNode convertBiNode(TreeNode root) { if (root == null) { return null; } search(root); return headNode; } /** * 中序遍歷框架 * search(node.left) * do current value * search(node.right) * @param node */ public void search(TreeNode node) { if (node == null) { return; } //1.遍歷左節點 search(node.left); //2.處理當前節點 if (preNode != null) { //當前節點設定為上個節點的右節點 preNode.right = node; } else { headNode = node; } //當前節點的左節點設定為null node.left = null; preNode = node; //3.遍歷右節點 search(node.right); }
例子2(刪除二叉搜尋樹中的 key 對應的節點)
給定一個二叉搜尋樹的根節點 root 和一個值 key,刪除二叉搜尋樹中的 key 對應的節點,並保證二叉搜尋樹的性質不變。返回二叉搜尋樹(有可能被更新)的根節點的引用。
一般來說,刪除節點可分為兩個步驟:
首先找到需要刪除的節點;
如果找到了,刪除它。
說明: 要求演算法時間複雜度為 O(h),h 為樹的高度。
分析:
-
當前節點沒有左子節點
返回root.right
-
當前節點沒有右子節點
返回root.left
-
當前節點既有左子節點和右子節點時
-
找到右子節點下面最後一個左子結點
-
將root的左子節點放到右子節點下面最後一個左子結點的左子節點上
-
直接返回右子節點
-
BTS數遍歷框架
二叉搜尋樹(Binary Search Tree,簡稱 BST)是一種很常用的的二叉樹。它的定義是:
一個二叉樹中,任意節點的值要大於等於左子樹所有節點的值,且要小於等於右邊子樹的所有節點的值
void BST(TreeNode root, int target) {
if (root.val == target)
// 找到目標,做點什麼
if (root.val < target)
//目標比節點值大,目標肯定在右節點
BST(root.right, target);
if (root.val > target)
//目標比節點值小,目標肯定在左節點
BST(root.left, target);
}
public TreeNode deleteNode(TreeNode root, int key) {
if(root == null) {
return null;
}
if(root.val == key){
if(root.right == null){
return root.left;
}
if(root.left == null) {
return root.right;
}
//當目標節點左右子節點都存在時
TreeNode node = root.right;
//找到右子節點下面最後一個左子結點
while(node.left != null){
node = node.left;
}
//將root的左子節點放到右子節點下面最後一個左子結點的左子節點上
node.left = root.left;
//直接返回右子節點
return root.right;
}else if(key < root.val){
root.left = deleteNode(root.left,key);
}else{
root.right = deleteNode(root.right,key);
}
return root;
}
例子3(根據前序中序遍歷結果重建二叉樹)
//根據前序中序遍歷結果重建二叉樹框架
//pre 前序
//mid 中序
TreeNode buildNode(List<Integer> pre,List<Integer> mid){
if(pre.size() == 0){
return null;
}
//前序第一個值肯定是根節點
TreeNode root = new TreeNode(pre.get(0));
//中序對應值的索引作為左右子樹分割點
int i = mid.indexOf(pre.get(0));
//重建左樹
root.left = buildNode(pre.subList(1,i+1),mid.subList(0,i));
//重建右樹
root.right = buildNode(pre.subList(i+1,pre.size()),mid.subList(i+1,mid.size()));
return root;
}
java程式碼
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
List<Integer> mid=new ArrayList<>();
List<Integer> pre=new ArrayList<>();
for(int i=0;i<preorder.length;i++){
pre.add(preorder[i]);
mid.add(inorder[i]);
}
return buildNode(pre,mid);
}
/**
*pre 前序
*mid 中序
*/
TreeNode buildNode(List<Integer> pre,List<Integer> mid){
if(pre.size() == 0){
//1.遞迴停止條件
return null;
}
//2.前序第一個是root節點
TreeNode root = new TreeNode(pre.get(0));
//3.找到中序中root節點的索引
//中序遍歷的順序是左->根->右,所以root節點的索引左邊一定是左子節點,右邊一定是右子節點,
//這樣就就分成左右兩部分了
int i = mid.indexOf(pre.get(0));
//這樣就處理完畢了,接下來就遞迴重複上面步驟了
//遞迴處理左節點資料,前序1->i+1,中序:0->i
root.left = buildNode(pre.subList(1,i+1),mid.subList(0,i));
//遞迴處理右節點資料,前序i+1->end,中序:i+1->end
root.right = buildNode(pre.subList(i+1,pre.size()),mid.subList(i+1,mid.size()));
return root;
}