js快速排序算法解析

數組的快速排序算法,和並歸排序步驟基本相似。javascript

都是先拆分,後合併。並歸排序是:拆分容易,合併難。 快速排序是:拆分難,合併容易java

 

要理解快速排序,首先要理解拆分邏輯算法

要素:找一個基準點,經過操做使得數列的左邊所有都是小於他的數,右邊所有都是大於他的數;數組

一、選中基準點,開始索引 i   ,結束索引  j函數

二、從數列右邊開始往左邊找,找到比基準點小的,交換位置 i++優化

三、從數列左邊開始往右邊找,找到比基準點大的,交換位置 j--ui

四、循環執行二、3,直到,i 不是小於 jcode

 

例如: 有數組  var arr = [30,24,5,58,18,36,12,42,39];blog

           開始索引  i = 0;  結束索引 j = arr.length-1;    基準點  pivot = arr[i]  即爲30排序

   則有以下代碼

      

var arr = [30,24,5,58,18,36,12,42,39];
		var i = 0, j = arr.length-1,pivot = arr[i];
		
		while(i < j ){  //當最後結束時 i = j
			//從右往左找,找到比基準點小等的就交換,交換後,基準點的索引變爲 j
			while(i < j && arr[j] > pivot )
				j--;  //排除已經知足條件的點                        
			if(i < j ){
				swap(i++,j,arr);
			}
			
			//從左往右找,找到比基準點大的就交換,交換後,基準點的索引變爲 i
			while(i < j && arr[i] <= pivot)
				i++; //排除已經知足條件的點
			if(i < j ){
				swap(i,j--,arr);
			}
		}
		
		function swap(a,b,arr){
			console.log(a,b,arr[a],arr[b])
			var temp = arr[a];
			arr[a] = arr[b];
			arr[b] = temp;
		}
	
		console.log(i,arr); //基準點i,處理好的arr

  

以上代碼就是快速排序的核心,若是將數列,不斷以上面方式細分,直到分爲單個元素。即最後的結果就是一個有序的數列

 

下面給出完整代碼

var arr = [30,24,5,58,18,36,12,42,39];
		
		function Partition(arr,low,high){
			var i = low,j = high,pivot = arr[i];
			
			while(i < j ){
				//從右往左找
				while(i < j && arr[j] > pivot )
					j--;                        
				if(i < j ){
					swap(i++,j,arr);
				}
				
				//從左往右找
				while(i < j && arr[i] <= pivot)
					i++; 
				if(i < j ){
					swap(i,j--,arr);
				}
			}

			return i;  //返回基準元素位置
		}
		
		function swap(a,b,arr){
			console.log(a,b,arr[a],arr[b])
			var temp = arr[a];
			arr[a] = arr[b];
			arr[b] = temp;
		}
		
		function QuickSort(arr,low,high){
			var mid;
			if(low < high){
				mid = Partition(arr,low,high); //返回基準元素位置
				QuickSort(arr,low,mid-1);   //左邊快速排序
				QuickSort(arr,mid+1,high);  //右邊快速排序
			}
		}
		QuickSort(arr,0,arr.length-1);
		console.log(arr);

  

 

優化擴展:

   上面的Partition函數中,無論是從右往左,仍是從左往右。都是跟pivot基準元素交換。。實際上,能夠先直接左邊和右邊交換,最後再和基準元素交換,減小交換次數。代碼以下

var arr = [30,24,5,58,18,36,12,42,39];
		var i = 0, j = arr.length-1,pivot = arr[i];
		var mid;
		while(i < j ){  //當最後結束時 i = j
			//從右往左找
			while(i < j && arr[j] > pivot )
				j--;  //排除已經知足條件的點                        
			//從左往右找
			while(i < j && arr[i] <= pivot)
				i++; //排除已經知足條件的點
			
			//找到兩個點,就相互交換
			if(i < j ){
				swap(i++,j--,arr);
			}
		}
		
		//最後將中間點和基準點交換
		if(arr[i] > pivot){
			mid = i-1;
			swap(0,mid,arr);
		}else{
			mid = i;
			swap(0,mid,arr);
		}
		
		function swap(a,b,arr){
			console.log(a,b,arr[a],arr[b])
			var temp = arr[a];
			arr[a] = arr[b];
			arr[b] = temp;
		}
	
		console.log(mid,arr); //基準點mid,處理好的arr

  

 

使用js的數組方法 , unshift 和push

使用unshift 和push實現,將數列的基準元素,左邊所有小於他,右邊所有大於他

           var arr = [30,24,5,58,18,36,12,42,39];
		var i = 0, pivot = arr[0], arr2 = [pivot];
		for(var j = 1; j < arr.length; j++ ){
			if(arr[j] > pivot){
				arr2.push(arr[j]);
			}else{
				arr2.unshift(arr[j]);
				i++;
			}
		}
		console.log(i,arr2);

  

使用 unshift和push實現的快速排序

var arr = [30,24,5,58,18,36,12,42,39];
		
		function Partition(arr,low,high){
			var i = low,pivot = arr[i];
			var arr2 = [pivot];
			for(var j = low+1; j <= high; j++){
				if(arr[j] > pivot){
					arr2.push(arr[j]);
				}else{
					arr2.unshift(arr[j]);
					i++;
				}
			}
			j = 0;
			for(var k = low ; k <= high ; k++){
				arr[k] = arr2[j++];
			}
			return i;  //返回基準元素位置
		}

		function QuickSort(arr,low,high){
			var mid;
			if(low < high){
				mid = Partition(arr,low,high); //返回基準元素位置
				QuickSort(arr,low,mid-1);   //左邊快速排序
				QuickSort(arr,mid+1,high);  //右邊快速排序
			}
		}
		QuickSort(arr,0,arr.length-1);
		console.log(arr);
相關文章
相關標籤/搜索