找到中序遍歷二叉樹下一個節點
分析二叉樹的下一個節點,一共有以下情況:
1.二叉樹為空,則返回空;
2.節點右孩子存在,則設置一個指針從該節點的右孩子出發,一直沿著指向左子結點的指針找到的葉子節點即為下一個節點;
3.節點不是根節點。如果該節點是其父節點的左孩子,則返回父節點;否則繼續向上遍歷其父節點的父節點,重復之前的判斷,返回結果。代碼如下
//8,6,10,5,7,9,11
/*
* 給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點并且返回。
* 注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指針。
*/
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
if(pNode==null)
return null;
if(pNode.right!=null){//如果有右子樹,找右子樹的最左節點
TreeLinkNode p=pNode.right;
while(p.left!=null){
p=p.left;
}
return p;
}
while(pNode.next!=null){//沒右子樹,則找第一個當前結點是父節點左孩子的節點
if(pNode.next.left==pNode)//節點不是根節點。如果該節點是其父節點的左孩子,則返回父節點;否則繼續向上遍歷
return pNode.next;
pNode=pNode.next;
}
return null;
}
class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null;
TreeLinkNode(int val) {
this.val = val;
}
}
之字形打印二叉樹
利用棧后進先出的特性,兩個棧一個存奇數層節點,一個存偶數層節點
/*
* 請實現一個函數按照之字形打印二叉樹,即第一行按照從左到右的順序打印,
* 第二層按照從右至左的順序打印,第三行按照從左到右的順序打印,其他行以此類推。
*/
//{8,6,10,5,7,9,11}
public static ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> all=new ArrayList<ArrayList<Integer>>();
int layer=1;
Stack<TreeNode> s1=new Stack<TreeNode>();
Stack<TreeNode> s2=new Stack<TreeNode>();
s1.push(pRoot);
while(!s1.empty()||!s2.empty()){
if(layer%2!=0){
ArrayList<Integer> temp=new ArrayList<Integer>();
while(!s1.empty()){
TreeNode node=s1.pop();
if(node!=null){
temp.add(node.val);
System.out.print(node.val + " ");
s2.push(node.left);
s2.push(node.right);
}
}
if(!temp.isEmpty()){
all.add(temp);
layer++;
System.out.println();
}
}else{
ArrayList<Integer> temp=new ArrayList<Integer>();
while(!s2.empty()){
TreeNode node=s2.pop();
if(node!=null){
temp.add(node.val);
System.out.print(node.val + " ");
s1.push(node.right);
s1.push(node.left);
}
}
if(!temp.isEmpty()){
all.add(temp);
layer++;
System.out.println();
}
}
}
return all;
}
多行打印二叉樹
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> result=new ArrayList<ArrayList<Integer>>();
if(pRoot==null)
return result;
Queue<TreeNode> layer=new LinkedList<>();
ArrayList<Integer> list=new ArrayList<Integer>();
layer.add(pRoot);
int start=0,end=1;
while(!layer.isEmpty()){
TreeNode cur=layer.remove();
list.add(cur.val);
start++;
if(cur.left!=null)
layer.add(cur.left);
if(cur.right!=null)
layer.add(cur.right);
if(start==end){
end=layer.size();
start=0;
result.add(list);
list=new ArrayList<>();
}
}
return result;
}
反轉鏈表
方法一
//反轉鏈表
ListNode reverseNode(ListNode phead){
ListNode preverhead=null;//保存翻轉后的頭結點 是原始鏈表的尾結點
ListNode pnode=phead;//當前節點
ListNode pprev=null;//當前節點的左一個節點
while(pnode!=null){
ListNode pnext=pnode.next;//當前節點的下一個節點
if(pnext==null)
preverhead=pnode;
pnode.next=pprev;
pprev=pnode;
pnode=pnext;
}
return preverhead;
}
方法二
public ListNode ReverseList(ListNode head) {
if(head==null)
return null;
ListNode pre=null;
ListNode next=null;
while(head!=null){
next=head.next;
head.next=pre;
pre=head;
head=next;
}
return pre;
}
合并兩個有序鏈表
方法一 遞歸
//合并兩個有序鏈表
public ListNode merge(ListNode node1,ListNode node2){
if(node1==null)
return node2;
else if(node2==null)
return node1;
ListNode p=null;
if(node1.val<node2.val){
p=node1;
p.next=merge(node1.next,node2);
}else{
p=node2;
p.next=merge(node2.next,node1);
}
return p;
}
方法二 新建一個頭結點
//新建一個頭結點的方式 合并有序鏈表
public ListNode Merge(ListNode list1,ListNode list2) {
ListNode head=new ListNode(-1);
head.next=null;
ListNode root=head;
while(list1!=null&&list2!=null){
if(list1.val<list2.val){
head.next=list1;
head=list1;
list1=list1.next;
}else{
head.next=list2;
head=list2;
list2=list2.next;
}
}
if(list1!=null)
head.next=list1;
if(list2!=null)
head.next=list2;
return root.next;
}
方法三 先賦值第一個節點
//先賦值第一個節點
public ListNode Merge2(ListNode list1,ListNode list2) {
ListNode head=null;
if(list1.val<=list2.val){
head=list1;
list1=list1.next;
}else{
head=list2;
list2=list2.next;
}
ListNode p=head;
while(list1!=null&&list2!=null){
if(list1.val<list2.val){
p.next=list1;
list1=list1.next;
}else{
p.next=list2;
list2=list2.next;
}
p=p.next;
}
if(list1!=null)
p.next=list1;
if(list2!=null)
p.next=list2;
return head;
}