1. 程式人生 > >連結串列經典演算法題實現

連結串列經典演算法題實現

本文包含連結串列的以下內容:

  1、單鏈表的建立和遍歷

  2、求單鏈表中節點的個數

  3、查詢單鏈表中的倒數第k個結點(劍指offer,題15)

  4、查詢單鏈表中的中間結點

  5、合併兩個有序的單鏈表,合併之後的連結串列依然有序【出現頻率高】(劍指offer,題17)

  6、單鏈表的反轉【出現頻率最高】(劍指offer,題16)

  7、從尾到頭列印單鏈表(劍指offer,題5)

  8、判斷單鏈表是否有環

  9、取出有環連結串列中,環的長度

  10、單鏈表中,取出環的起始點(劍指offer,題56)。本題需利用上面的第8題和第9題。

  11、判斷兩個單鏈表相交的第一個交點(劍指offer,題37)

package com.he;

import java.util.Stack;

import com.he.LinkList.Node;

public class test32 {
	class Node{
		int data;
		Node next;
		Node(int data){
			this.data = data;
		}
	}
	public Node head =null;
    public Node current = null;
    //新增節點
    public void add(int data){
    	if(head==null){
    		head = new Node(data);
    		current = head;
    	}else{
    		current.next = new Node(data);
    		current = current.next;
    	}
    }
    //方法過載:向連結串列中新增結點
    public void add(Node node){
    	if(head==null){
    		head = node;
    		current = node;
    	}else{
    		current.next = node;
    		current = current.next;
    	}
    }
    
    //遍歷節點
    public void print(Node node){
        current = node;
        while(current!=null){
        	System.out.println(current.data);
        	current = current.next;
        }
    }
    //求單鏈表節點
    public int getLength(Node node){
    	current = node;
    	int length = 0;
    	if(current == null){
    		return 0;
    	}
    	while(current!=null){
    		length++;
    		current = current.next;   		
    	}
		return length;  
    	
    }
    //查詢單鏈表中的倒數第k個結點
    public Node findLastNode(Node node,int k){
    	if(node==null || k==0){
    		return null;
    	}
    	Node first = node;
    	Node second = node;
    	for (int i = 0; i < k-1; i++) {
			second = second.next;
			if(second == null){
				return null;
			}
		}
    	while(second.next!=null){
    		first = first.next;
    		second = second.next;
    	}
    	return first;
    }
    
    //查詢單鏈表中的中間結點
    public Node findMiddle(Node node){
    	if(node==null){
    		return null;
    	}
    	Node first = node;
    	Node second = node;
    	while(first!=null && second!=null){
    		if(second.next!=null){
    			second = second.next.next;
    		}else{
    			return first;
    		}   
    		first = first.next;
    	}
    	return first;
    }
   
    //合併兩個有序的單鏈表,合併之後的連結串列依然有序
    public Node getMergeLinkList(Node head1,Node head2){
    	if(head1==null && head2==null){
    		return null;
    	}
    	if(head1==null){
    		return head2;
    	}
    	if(head2==null){
    		return head1;
    	}
    	Node head;
    	Node current;
    	if(head1.data < head2.data){
    		head = head1;
    		current = head1;
    		head1 = head1.next;
    	}else{
    		head = head2;
    		current = head2;
    		head2 = head2.next;
    	}
    	while(head1!= null && head2!= null){
    		if(head1.data < head2.data){
    			current.next = head1;
    			current = current.next;
    			head1 = head1.next;
    		}else{
    			current.next = head2;
    			current = current.next;
    			head2 = head2.next;
    		}
    	}
    	if(head1 == null){
    		current.next = head2;
    	}
    	if(head2 == null){
    		current.next = head1;
    	}
    	return head;
    }
    //單鏈表的反轉
    public Node reverseList(Node head){
    	if(head==null && head.next==null){
    		return head;
    	}
    	Node reverseHead = null;
    	Node next = null;
    	Node current = head;
    	while(current!=null){
    		next = current.next;
    		current.next = reverseHead;
    		reverseHead = current;
    		current = next;
    	}
    	return reverseHead;
    }
    
    //從尾到頭列印單鏈表
    public void reversePrint(Node head){
    	if(head == null){
    		return;
    	}
    	Stack<Node> stack = new Stack<Node>();
    	Node current = head;
    	while(current!=null){
    		stack.push(current);
    		current = current.next;
    	}
    	while(stack.size()>0){
    		System.out.println(stack.pop().data);
    	}
    }
    
    //判斷單鏈表是否有環
    public boolean hasCycle(Node head){
    	if(head == null){
    		return false;
    	}
    	Node first = head;
    	Node second = head;
    	while(second!=null){
    		first = first.next;
    		if(second.next!=null){
    			second = second.next.next;
    		}else{
    			return false;
    		}    		
    		if(first == second){
    			return true;
    		}
    	}
    	return false;
    }
   
    //取出有環連結串列中,環的長度
    public int getCycleLength(Node node){
    	int length = 0;
    	Node current = node;
    	while(current!=null){
    		current = current.next;
    		length++;
    		if(current == node){
    			return length;
    		}
    	}
    	return length;
    }
    
    //單鏈表中,取出環的起始點
    public Node getCycleStart(Node head,int cycleLength){
    	if(head==null){
    		return null;
    	}
    	Node first = head;
    	Node second = head;
    	for (int i = 0; i < cycleLength; i++) {
			second = second.next;
		}
    	while(first!=null&& second!=null){
    		if(first == second){
    			return first;
    		}
    		first = first.next;
    		second = second.next;
    	}
    	return null;
    }
    
    //求兩個單鏈表相交的第一個交點
    public Node getFirstCommonNode(Node head1,Node head2){
    	if(head1==null|| head2==null){
    		return null;
    	}
    	int length1 = getLength(head1);
    	int length2 = getLength(head2);
    	int lengthDif = 0;
    	Node longHead = null;
    	if(length1 > length2){
    		lengthDif = length1-length2;
    		longHead = head1;
    	}else{
    		lengthDif = length2-length1;
    		longHead = head2;
    	}
    	for (int i = 0; i < lengthDif; i++) {
		    longHead = longHead.next;	
		}
    	while(longHead!=null && head2!=null){
    		longHead = longHead.next;
    		head2 = head2.next;
    		if(longHead == head2){
    			return head2;
    		}
    	}
		return null;    	
    }
    
    public static void main(String[] args) {
	    test32 sh = new test32();
	    for (int i = 0; i < 4; i++) {
			sh.add(i);
		}
	   // sh.print(sh.head);
	   // System.out.println(sh.getLength(sh.head));
	   // System.out.println(sh.findLastNode(sh.head, 3).data);
	   //sh.print(sh.reverseList(sh.head));
	    sh.add(sh.head);
	    System.out.println(sh.hasCycle(sh.head));
	    System.out.println(sh.hasCycle(sh.head));
	    System.out.println(sh.getCycleLength(sh.head));
	    System.out.println(sh.getCycleStart(sh.head, sh.getCycleLength(sh.head)).data);	      
//	    test32 sh1 = new test32();
//	    for (int i = 6; i < 8; i++) {
//			sh1.add(i);
//		} 
//	    sh.print(sh.getMergeLinkList(sh.head, sh1.head));
	    
	}
}