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

歡迎訪問 生活随笔!

生活随笔

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

java

【Java】 剑指offer(36) 二叉搜索树与双向链表

發布時間:2025/4/16 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java】 剑指offer(36) 二叉搜索树与双向链表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文參考自《劍指offer》一書,代碼采用Java語言。

更多:《劍指Offer》Java實現合集??

題目 

  輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。

思路

  二叉搜索樹、排序鏈表,想到使用中序遍歷。

  要實現雙向鏈表,必須知道當前結點的前一個結點。根據中序遍歷可以知道,當遍歷到根結點的時候,左子樹已經轉化成了一個排序的鏈表了,根結點的前一結點就是該鏈表的最后一個結點(這個結點必須記錄下來,將遍歷函數的返回值設置為該結點即可),鏈接根結點和前一個結點,此時鏈表最后一個結點就是根結點了。再處理右子樹,遍歷右子樹,將右子樹的最小結點與根結點鏈接起來即可。左右子樹的轉化采用遞歸即可。

  大概思想再理一下:首先想一下中序遍歷的大概代碼結構(先處理左子樹,再處理根結點,之后處理右子樹),假設左子樹處理完了,就要處理根結點,而根結點必須知道左子樹的最大結點,所以要用函數返回值記錄下來;之后處理右子樹,右子樹的最小結點(也用中序遍歷得到)要和根結點鏈接。

  注意搞清楚修改后的中序遍歷函數的意義(見代碼注釋)

測試算例 

  1.功能測試(一個結點;左右斜樹;完全二叉樹;普通二叉樹)

  2.特殊測試(根結點為null)

Java代碼

//題目:輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求 //不能創建任何新的結點,只能調整樹中結點指針的指向。public class ConvertBinarySearchTree {public class TreeNode {int val = 0;TreeNode left = null;TreeNode right = null;public TreeNode(int val) {this.val = val;}}public TreeNode convert(TreeNode head) {if(head==null)return head;TreeNode lastNodeInList=null;lastNodeInList=convertHelper(head,lastNodeInList);TreeNode firstNodeInList=lastNodeInList;while(firstNodeInList.left!=null) {firstNodeInList=firstNodeInList.left;} return firstNodeInList;}//將以node為根結點的樹轉化為排序鏈表,鏈表頭部與lastNode鏈接,并返回最后一個結點private TreeNode convertHelper(TreeNode node,TreeNode lastNode) {//處理左子樹,獲得最大結點if(node.left!=null)lastNode=convertHelper(node.left, lastNode);//鏈接最大結點和根結點node.left=lastNode;if(lastNode!=null)lastNode.right=node;//處理右子樹lastNode=node;if(node.right!=null)lastNode=convertHelper(node.right, lastNode);return lastNode;} }

  

上面的代碼是參考《劍指OFFER》寫的,下面的代碼是復習時重新寫過的,思路比較簡潔一點。非遞歸方法的核心是中序遍歷的非遞歸實現。

public class Solution {/** 遞歸版本* 1.已知函數返回的是轉換好的雙向鏈表頭結點* 2.左子樹處理完后與根結點連接* 3.右子樹處理,也與根結點連接* 4.最后返回頭結點*/public TreeNode Convert(TreeNode root) {if (root == null)return root;// 處理左子樹,獲得左子樹鏈表的頭結點TreeNode left = Convert(root.left);TreeNode p = left;if (left != null) {// 找到左子樹鏈表的末尾結點while (p.right != null)p = p.right;// 連接結點p.right = root;root.left = p;}// 處理右子樹,獲得右子樹鏈表的頭結點TreeNode right = Convert(root.right);// 連接結點if (right != null) {root.right = right;right.left = root;}return left == null ? root : left;}/* 非遞歸版本* 1.利用非遞歸中序遍歷來連接結點*/public TreeNode Convert1(TreeNode root) {TreeNode head = null;TreeNode pre = null;LinkedList<TreeNode> stack = new LinkedList<>();while (root != null || !stack.isEmpty()) {// 把root當作指針使用while (root != null) {stack.push(root);root = root.left;}TreeNode node = stack.pop();if (head == null) {head = node;pre = node;} else {node.left = pre;pre.right = node;pre = node; // 別漏寫了}root = node.right;}return head;} }

  

收獲

  題目較復雜時,不要慌。這道題和中序遍歷有關,把樹分為三部分:根結點、左子樹和右子樹,思考在中序遍歷中根結點應該如何處理,這是關鍵——要將左子樹的最大結點、根結點、右子樹的最小結點鏈接起來。左右子樹的處理是相同的,因此采用遞歸。

?

更多:《劍指Offer》Java實現合集??

  

轉載于:https://www.cnblogs.com/yongh/p/9860700.html

總結

以上是生活随笔為你收集整理的【Java】 剑指offer(36) 二叉搜索树与双向链表的全部內容,希望文章能夠幫你解決所遇到的問題。

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