日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 3 4_Java-3/4_树.md at master · yrcDream/Java-3 · GitHub

發布時間:2025/3/12 java 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 3 4_Java-3/4_树.md at master · yrcDream/Java-3 · GitHub 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

二叉樹

二叉樹具有唯一根節點

二叉樹每個節點最多有兩個孩子,最多有一個父親

二叉樹具有天然遞歸結構

二叉樹不一定是 “滿” 的:一個節點也是二叉樹、空節點也是二叉樹

二叉搜索樹(BST)

BST 的基本功能

public class BST> {

private Node root;

private int size;

public BST(){

root=null;

size=0;

}

public int size(){

return size;

}

public boolean isEmpty(){

return size==0;

}

private class Node{

public E e;

public Node left,right;

public Node(E e){

this.e=e;

this.left=null;

this.right=null;

}

}

}

添加元素

思路

對于如下的 BST,向其中添加 28:

28 與根結點 41 比較,應該插入左子樹

28 與左子樹的根結點 22 比較,應該插入該結點的右子樹

28 與 33 比較,應該插入該結點的左子樹,該結點的左子樹為空,則將值為 28 的結點添加到該結點的左子樹中

最終將 28 添加到該 BST 中

代碼

//向BST中添加新元素e

public void add(E e){

if(root==null){

root=new Node(e);

size++;

return;

}else{

add(root,e);

}

}

//向以node為根節點的BST樹種插入元素e

private void add(Node node,E e){

if(e.equals(node.e)){

//插入元素與根節點相等,直接返回

return;

}else if(e.compareTo(node.e)<0 && node.left==null){

node.left=new Node(e);

size++;

return;

}else if(e.compareTo(node.e)>0 && node.right==null){

node.right=new Node(e);

size++;

return;

}

if(e.compareTo(node.e)<0){

add(node.left,e);

}else{ //e.compareTo(node.e)>0

add(node.right,e);

}

}

改進添加元素

前文中的添加操作,對 root==null 的情況進行了特殊處理,并且 add(Node,E) 中的遞歸條件也太冗長了。

這里我們寫一個 add() 方法,返回插入新節點后該 BST 的根節點

//向BST中添加新元素e

public void add(E e){

root=add(root,e);

}

//向以node為根節點的BST樹種插入元素e

//返回插入新元素后該BST的根

private Node add(Node node,E e){

if(node==null){

size++;

return new Node(e);

}

//注意:對于e.equals(node.e)不做處理

if(e.compareTo(node.e)<0){

node.left=add(node.left,e);

}else if(e.compareTo(node.e)>0){

node.right=add(node.right,e);

}

return node;

}

查詢元素

//查看BST中是否包含元素e

public boolean contains(E e){

return contains(root,e);

}

//查看以node為根節點的BST中是否包含元素e

private boolean contains(Node node,E e){

if(node==null){

return false;

}

if(e.compareTo(node.e)==0){

return true;

}else if(e.compareTo(node.e)<0){

return contains(node.left,e);

}else{

return contains(node.right,e);

}

}

遍歷元素(遞歸形式)

前序遍歷

//BST的前序遍歷

public void preOrder(){

preOrder(root);

}

private void preOrder(Node node){

if(node==null){

return;

}

System.out.println(node.e);

preOrder(node.left);

preOrder(node.right);

}

/**

* 利用前序遍歷打印 BST

*/

@Override

public String toString() {

StringBuilder res=new StringBuilder();

generateBST(root,0,res);

return res.toString();

}

//生成以node為根節點,深度為depth的描述二叉樹的字符串(利用前序遍歷)

private void generateBST(Node node,int depth,StringBuilder res){

if(node==null){

res.append(generateDepth(depth)+"null\n");

return;

}

res.append(generateDepth(depth)+node.e+"\n");

generateBST(node.left,depth+1,res);

generateBST(node.right,depth+1,res);

}

private String generateDepth(int depth){

StringBuilder res=new StringBuilder();

for(int i=0;i

res.append("--");

}

return res.toString();

}

中序遍歷

//BST的中序遍歷

public void inOrder(){

inOrder(root);

}

private void inOrder(Node node){

if(node==null){

return;

}

inOrder(node.left);

System.out.println(node.e);

inOrder(node.right);

}

后序遍歷

//BST的后序遍歷

public void postOrder(){

postOrder(root);

}

private void postOrder(Node node){

if(node==null){

return;

}

postOrder(node.left);

postOrder(node.right);

System.out.println(node.e);

}

遍歷元素(非遞歸形式)

//枚舉命令,GO表示訪問元素,COUT表示打印元素

private enum Command{GO,COUT};

private class StackNode{

Command command;

Node node;

StackNode(Command command,Node node){

this.command=command;

this.node=node;

}

}

前序遍歷

//BST的前序遍歷(非遞歸方式)

public void preOrderNR(){

preOrderNR(root);

}

private void preOrderNR(Node node){

if(node==null){

return;

}

Stack stack=new Stack<>();

stack.push(new StackNode(Command.GO,node));

while(!stack.isEmpty()){

StackNode stackNode=stack.pop();

Node n=stackNode.node;

Command command=stackNode.command;

if(command==Command.COUT){

System.out.println(stackNode.node.e);

}else{

if(n.right!=null){

stack.push(new StackNode(Command.GO,n.right));

}

if(n.left!=null){

stack.push(new StackNode(Command.GO,n.left));

}

stack.push(new StackNode(Command.COUT,n));

}

}

}

中序遍歷

//BST的中序遍歷(非遞歸方式)

public void inOrderNR(){

inOrderNR(root);

}

private void inOrderNR(Node node){

if(node==null){

return;

}

Stack stack=new Stack<>();

stack.push(new StackNode(Command.GO,node));

while(!stack.isEmpty()){

StackNode stackNode=stack.pop();

Node n=stackNode.node;

Command command=stackNode.command;

if(command==Command.COUT){

System.out.println(stackNode.node.e);

}else{

if(n.right!=null){

stack.push(new StackNode(Command.GO,n.right));

}

stack.push(new StackNode(Command.COUT,n));

if(n.left!=null){

stack.push(new StackNode(Command.GO,n.left));

}

}

}

}

后序遍歷

//BST的后序遍歷(非遞歸方式)

public void postOrderNR(){

postOrderNR(root);

}

private void postOrderNR(Node node){

if(node==null){

return;

}

Stack stack=new Stack<>();

stack.push(new StackNode(Command.GO,node));

while(!stack.isEmpty()){

StackNode stackNode=stack.pop();

Node n=stackNode.node;

Command command=stackNode.command;

if(command==Command.COUT){

System.out.println(stackNode.node.e);

}else{

stack.push(new StackNode(Command.COUT,n));

if(n.right!=null){

stack.push(new StackNode(Command.GO,n.right));

}

if(n.left!=null){

stack.push(new StackNode(Command.GO,n.left));

}

}

}

}

層序遍歷

//BST的層序遍歷

public void levelOrder(){

Queue q=new LinkedList<>();

q.add(root);

while(!q.isEmpty()){

Node node=q.remove();

System.out.println(node.e);

if(node.left!=null){

q.add(node.left);

}

if(node.right!=null){

q.add(node.right);

}

}

}

刪除元素

刪除最小值和最大值

尋找 BST 中的最小元素和最大元素

//尋找BST中的最小元素

public E min(){

if(size==0){

throw new IllegalArgumentException("BST is emmpty");

}

return min(root).e;

}

private Node min(Node node){

if(node.left==null){

return node;

}

return min(node.left);

}

//尋找BST中的最大元素

public E max(){

if(size==0){

throw new IllegalArgumentException("BST is emmpty");

}

return max(root).e;

}

private Node max(Node node){

if(node.right==null){

return node;

}

return max(node.right);

}

刪除BST中的最大值和最小值

情況一:最小值是葉子節點。直接刪除該節點

情況二:最小值有右子樹。刪除該節點,再將該節點的右子樹連接到原來的 BST 中

代碼:

//刪除BST中的最小值

public E delMin(){

E res=min();

delMin(root);

return res;

}

//刪除以node為根結點的BST中的最小值元素

//這里考慮最小值只有右子樹的情況,因為葉子節點是其特例

private Node delMin(Node node){

if(node.left==null){

Node nodeRight=node.right;

node.right=null;

size--;

return nodeRight;

}

node.left=delMin(node.left);

return node;

}

//刪除BST中的最大值

public E delMax(){

E res=max();

delMax(root);

return res;

}

//刪除以node為根結點的BST中的最大值元素

private Node delMax(Node node){

if(node.right==null){

Node nodeLeft=node.left;

node.left=null;

size--;

return nodeLeft;

}

node.right=delMax(node.right);

return node;

}

刪除任意元素

刪除只有左孩子的節點。直接刪除即可

刪除只有右孩子的節點。直接刪除即可

刪除左右孩子都有的節點

Habbard-Deletion:

d 是待刪除的節點,s 節點是 d 的后繼,也就是 d 的右子樹的最小值所在的節點。

注意:這里選擇左子樹的最大值所在的節點效果也是相同的。

使用 s 代替 d

最后刪除 d 節點

代碼

//刪除BST中任意元素

public void del(E e){

root=del(root,e);

}

private Node del(Node node,E e){

if(node==null){

return null;

}

if(e.compareTo(node.e)<0){

node.left=del(node.left,e);

return node;

}else if(e.compareTo(node.e)>0){

node.right=del(node.right,e);

return node;

}else{

//節點node就是要刪除的節點

//該節點只右有子樹

if(node.left==null){

Node rightNode=node.right;

node.right=null;

size--;

return rightNode;

}

//該節點只有左子樹

if(node.right==null){

Node leftNode=node.left;

node.left=null;

size--;

return leftNode;

}

//刪除既有左子樹又有右子樹的節點

Node s=min(node.right);

s.right=delMin(node.right);

s.left=node.left;

//刪除node

node.left=node.right=null;

return s;

}

}

哈夫曼樹

哈夫曼樹的構造過程

首先生成一顆哈夫曼樹,每次生成過程中選取頻率最少的兩個節點,生成一個新節點作為它們的父節點,并且新節點的頻率為兩個節點的和。選取頻率最少的原因是,生成過程使得先選取的節點位于樹的更低層,那么需要的編碼長度更長,頻率更少可以使得總編碼長度更少。

生成編碼時,從根節點出發,向左遍歷則添加二進制位 0,向右則添加二進制位 1,直到遍歷到葉子節點,葉子節點代表的字符的編碼就是這個路徑編碼。

舉例:

給定了四個結點a,b,c,d,權值分別為7,5,2,4。

找出現有權值中最小的兩個,2 和 4 ,相應的結點 c 和 d 構建一個新的二叉樹,樹根的權值為 2 + 4 = 6,同時將原有權值中的 2 和 4 刪掉,將新的權值 6 加入。

重復之前的步驟。

所有的結點構建成了一個全新的二叉樹,這就是哈夫曼樹。

代碼

public class Huffman {

private class Node implements Comparable {

char ch;

int freq;

boolean isLeaf;

Node left, right;

public Node(char ch, int freq) {

this.ch = ch;

this.freq = freq;

isLeaf = true;

}

public Node(Node left, Node right, int freq) {

this.left = left;

this.right = right;

this.freq = freq;

isLeaf = false;

}

@Override

public int compareTo(Node o) {

return this.freq - o.freq;

}

}

public Map encode(Map frequencyForChar) {

PriorityQueue priorityQueue = new PriorityQueue<>();

for (Character c : frequencyForChar.keySet()) {

priorityQueue.add(new Node(c, frequencyForChar.get(c)));

}

while (priorityQueue.size() != 1) {

Node node1 = priorityQueue.poll();

Node node2 = priorityQueue.poll();

priorityQueue.add(new Node(node1, node2, node1.freq + node2.freq));

}

return encode(priorityQueue.poll());

}

private Map encode(Node root) {

Map encodingForChar = new HashMap<>();

encode(root, "", encodingForChar);

return encodingForChar;

}

private void encode(Node node, String encoding, Map encodingForChar) {

if (node.isLeaf) {

encodingForChar.put(node.ch, encoding);

return;

}

encode(node.left, encoding + '0', encodingForChar);

encode(node.right, encoding + '1', encodingForChar);

}

}

總結

以上是生活随笔為你收集整理的java 3 4_Java-3/4_树.md at master · yrcDream/Java-3 · GitHub的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。