插入排序

插入排序(Insertion Sort)是一種簡單直觀的排序演算法。它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。插入排序在實現上,通常採用in-place排序(即只需用到O(1)的額外空間的排序),因而在從後向前掃描過程中,需要反覆把已排序元素逐步向後挪位,為最新元素提供插入空間。

時間複雜度:O(n^2);

1.直接插入法

演算法描述:
    1.從第一個元素開始,該元素可以認為已經被排序
    2.取出下一個元素,在已經排序的元素序列中從後向前掃描
    3.如果該元素(已排序)大於新元素,將該元素移到下一位置
    4.重複步驟3,直到找到已排序的元素小於或者等於新元素的位置
    5.將新元素插入到該位置後
    6.重複步驟2~5
動畫演示

2.折半插入排序(參考之前的二分查詢)

用折半查詢方法確定插入位置的排序。思想類似直接插入排序,只不過,要設定 mid=不大於(low+high)/2的最大整數,當插入到 mid 左邊(做半區),則改變 high(mid-1),如果插入到 mid 右邊,則改變 low(mid+1)。

初試序列,同樣是把第一個記錄看成是有序的子序列,然後從第二個記錄開始,依次進行比較

假設只有最後的20這個記錄了

mid=(0+6)/2=3,指向39處,20比mid 的值小,插入到 mid 左邊,改變 high=mid-1

重新計算 mid=1,指向13處,繼續和20比較,20比 mid的值大,插入到 mid 右邊,改變 low=mid+1

計算 mid=2,指向30,20比 mid 的值30小,插入到 mid 左邊,改變 high=mid-1

直到low>high時,由折半查詢得到的插入位置為low或high+1。

java程式碼實現直接插入排序:

package sortInsertDirec;


/*
 * java連結串列實現直接插入排序
 */
public class SortInsertDirec {
	public int[] sort(int data[]){
		int out[]=new int[data.length];
		
		ListNode head=new ListNode(data[0]);
		ListNode temp=head;
		
		for(int i=1;i<data.length;i++){
			temp.next=new ListNode(data[i]);
			temp=temp.next;
		}
		
		ListNode curNode=head.next;
		ListNode curNextNode=null;
		
		head.next=null;
		while(curNode!=null){
			curNextNode=curNode.next;
			temp=head;
			ListNode tempPre=null;
			while(temp!=null){
				if(curNode.val>temp.val){
					break;
				}
				tempPre=temp;
				temp=temp.next;
			}
			if(tempPre==null){
				head=curNode;
				curNode.next=temp;
			}else{
				tempPre.next=curNode;
				curNode.next=temp;
			}
			curNode=curNextNode;
		}
		
		int mm=0;
		while(head!=null){
			out[mm]=head.val;
			mm++;
			head=head.next;
		}
		
		return out;
	}
	
	public class ListNode{
		int val;
		ListNode next;
		ListNode(int x){
			val=x;
			next=null;
		}
	}
	public static void main(String args[]){
		int data[]={7,3,8,7,9,1,6,2,10};
		SortInsertDirec sc=new SortInsertDirec();
		data=sc.sort(data);
		for(int i=0;i<data.length;i++){
			System.out.print(data[i]+" ");
		}
	}
}

第二種實現方法:

package code.sortInsert;
import code.sortList.*;

public class Solution {
    public ListNode insertionSortList(ListNode head) {
    	//啞節點
        ListNode dumy = new ListNode(Integer.MIN_VALUE);
        ListNode cur = head;
        ListNode pre = dumy;
        while (cur != null) {
        	//儲存當前節點下一個節點
        	ListNode next = cur.next;
            pre = dumy;
            //尋找當前節點正確位置的一個節點
            while (pre.next != null && pre.next.val < cur.val) {
            	pre = pre.next;
            }
            //將當前節點加入新連結串列中
			cur.next = pre.next;
			pre.next = cur;
			//處理下一個節點
			cur = next;
        }
        return dumy.next;
        }
    
    public static void main(String args[]){
		int data[]={7,3,8,7,9,1,6,2,10};
		
		Solution s=new Solution();
		ListNode head=new ListNode(data[0]);
		ListNode temp=head;
		
		for(int i=1;i<data.length;i++){
			temp.next=new ListNode(data[i]);
			temp=temp.next;
		}
		head=s.insertionSortList(head);
	
		int out[]=new int[data.length];
		int mm=0;
		while(head!=null){
			out[mm]=head.val;
			mm++;
			head=head.next;
		}
		for(int i=0;i<out.length;i++){
			System.out.print(out[i]+" ");
		}
	}
}