關於對常見的幾種排序的理解。

排序這個東西是我們經常要用到的,下面談一談我對排序的理解。

(1)插入排序:插入排序是指先將元素的第一個數當做一個有序的表,然後把第二個元素與第一個元素之間進行比較,插入最開始有序表中,從第二個元素開始,每一個元素都與前面的有序表比較,並加入這個有序表。最後得到一個完全有序的序列。

         因爲在比較過程中,如果待插入的元素如果與有序表中的某個元素相比,是相等的。那麼這個元素就插入在後面,所以插入排序是穩定的。時間複雜度:O(n^2),其他插入排序:2分插入

執行的效果如下圖:

// 插入排序
var arr = [1, 4, 5, 7, 3, 2];
function insertSort(arr, length) {
  var temp;
  for (var i= 0; i < length; i++) {
    if (arr[i]>arr[i+1]) {
      temp = arr[i+1];
      for (var j=i;j>=0&&temp<arr[j];j--){
        console.log(123)
        arr[j+1]=arr[j];
      }
      arr[j+1]=temp
    }
  }
  return arr;
}
console.log(insertSort(arr, arr.length))




(2)希爾排序:希爾排序是插入排序的改進,希爾排序按照一個給定的2k,k,k/2...1這樣的數來將一堆需要排序的數劃分成幾個子序列,進行插入排序,然後再將一個基本有序的序列,再進行直接插入排序。

       比如說給定一個序列 1 7 6 5 9 2 0 以2劃分子序列是 1 5 0,7 9,6 2,對這三個子序列分別進行插入排序,最後再進行直接插入排序。因爲在子序列的直接插入過程中,很可能會造成一個數據與另一個子序列中的數據相同,但是卻改變了位置,所以希爾排序是一個不穩定的排序。

// 插入排序
void ShellSort(int arr[], int length)
{
	int increasement = length;
	int i, j, k;
	do
	{
		// 確定分組的增量
		increasement = increasement / 3 + 1;
		for (i = 0; i < increasement; i++)
		{
			for (j = i + increasement; j < length; j += increasement)
			{
				if (arr[j] < arr[j - increasement])
				{
					int temp = arr[j];
					for (k = j - increasement; k >= 0 && temp < arr[k]; k -= increasement)
					{
						arr[k + increasement] = arr[k];
					}
					arr[k + increasement] = temp;
				}
			}
		}
	} while (increasement > 1);
}

(3)堆排序:堆其實就是一個完全二叉樹,而且必須滿足根節點必須大於等於子節點或者小於等於孩子節點。

堆排序分成兩個過程:

      第一個過程是構建最大堆或者最小堆。一個排序後祖先節點就是最大的數或者最小的數。

      第二個過程就是排序了,將第一個過程得到祖先節點存入數組中,然後將最後一個葉子節點換到第一個過程得到的祖先節點上,再進行構造最大堆或者最小堆,依次這樣直到剩下最後一個葉子節點。

      堆排序是不穩定的排序

(4)選擇排序:選擇排序是指在一個給定的序列中,如果是從小到大排序,首先選擇一個最小的數與第一個數交換,然後從第二個數到最後一個數中選擇一個最小的數與第二個數交換,依次進行,直到n-1個元素與第n個元素比較。

        選擇排序是不穩定的排序。

// 選擇排序
var arr = [1, 4, 5, 7, 3, 2];
function selectionSort(arr, length) {
  var temp;
  for (var i= 0; i < length; i++) {
    for (var j = i; j < length - 1; j++) {
      if (arr[j] > arr[j+1]) {
        temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
      }
    }
    if (arr[j] >= arr[i]) {
      temp = arr[j];
        arr[j] = arr[i];
        arr[i] = temp;
    }
    console.log(arr[j])
  }
  return arr;
}
console.log(selectionSort(arr, arr.length))

(5)交換排------冒泡排序:這個是我第一個接觸的排序,主要思想是第一個數依次與第二-最後一個數進行比較,然後進行交互,依次進行,直到n-1個數與第n個數進行比較。

      冒泡排序是穩定的排序。

(6)快速排序:這個排序是目前非常火的一個排序,當序列是分佈隨機的,用快速排序的平均時間是最快的。當排序的數特別大,比如從10000個數中選取最小的十個時用堆排序。

快速排序的思想是給定一個序列,給定兩個遊標i,j分別指向序列的頭和尾(假設以升序排列)。(1)讓i和j指向的數進行比較,如果不發生交互,j向後走1,如果一直不發生交換,則j與i重合,則這一趟排序將待排序的序列分成了左右兩個部分----i後面的元素都比i大,如果發生交換,則i+1,然後與j比較,如果又發生交換,j-1,直到i,j重合,一趟排序完畢。

快速排序是不穩定的排序。

void QuickSort(int arr[], int start, int end)
{
	if (start >= end)
		return;
	int i = start;
	int j = end;
	// 基準數
	int baseval = arr[start];
	while (i < j)
	{
		// 從右向左找比基準數小的數
		while (i < j && arr[j] >= baseval)
		{
			j--;
		}
		if (i < j)
		{
			arr[i] = arr[j];
			i++;
		}
		// 從左向右找比基準數大的數
		while (i < j && arr[i] < baseval)
		{
			i++;
		}
		if (i < j)
		{
			arr[j] = arr[i];
			j--;
		}
	}
	// 把基準數放到i的位置
	arr[i] = baseval;
	// 遞歸
	QuickSort(arr, start, i - 1);
	QuickSort(arr, i + 1, end);
}

(7)歸併排序:把一個序列分成兩個或兩個以上的多個子序列,分別將各個子序列排列有序,然後合併成一個有序序列。


void MergeSort(int arr[], int start, int end, int * temp)
{
	if (start >= end)
		return;
	int mid = (start + end) / 2;
	MergeSort(arr, start, mid, temp);
	MergeSort(arr, mid + 1, end, temp);
 
	// 合併兩個有序序列
	int length = 0; // 表示輔助空間有多少個元素
	int i_start = start;
	int i_end = mid;
	int j_start = mid + 1;
	int j_end = end;
	while (i_start <= i_end && j_start <= j_end)
	{
		if (arr[i_start] < arr[j_start])
		{
			temp[length] = arr[i_start]; 
			length++;
			i_start++;
		}
		else
		{
			temp[length] = arr[j_start];
			length++;
			j_start++;
		}
	}
	while (i_start <= i_end)
	{
		temp[length] = arr[i_start];
		i_start++;
		length++;
	}
	while (j_start <= j_end)
	{
		temp[length] = arr[j_start];
		length++;
		j_start++;
	}
	// 把輔助空間的數據放到原空間
	for (int i = 0; i < length; i++)
	{
		arr[start + i] = temp[i];
	}
}

(8)冒泡排序

       首先從數組的第一個元素開始到數組最後一個元素爲止,對數組中相鄰的兩個元素進行比較,如果位於數組左端的元素大於數組右端的元素,則交換這兩個元素在數組中的位置,此時數組最右端的元素即爲該數組中所有元素的最大值。接着對該數組剩下的n-1個元素進行冒泡排序,直到整個數組有序排列。算法的時間複雜度爲O(n^2)。

附上冒泡排序JavaScript實現方法:

// 冒泡排序
var arr = [1, 4, 5, 7, 3, 2];
function bubbleSort(arr, length) {
  var temp;
  for (var i= 0; i < length; i++) {
    var flag = 0;
    for (var j = 0; j < length - i - 1; j++) {
      if (arr[j] > arr[j+1]) {
        temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
        flag = 1;
      }
    }
    if (!flag) {
      break;
    } 
  }
  return arr;
}
console.log(bubbleSort(arr, arr.length))

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章