數據結構 || 常見的排序算法@選擇排序

選擇排序

  • 基本思想:每一次從待排序的數據元素中選出最小的(或最大的)一個元素,存放在序列的起始位置,直到全所有的待排序元素排完.

直接選擇排序

  • 在元素集合a[i]到a[n-1]之中選擇關鍵碼最大(最小)的數據元素

  • 若它不是這組元素中的最後一個(第一個)元素,則將它與這組元素中的最後一個(第一個)元素交換

  • 在剩餘的array[i]—array[n-2] /array[i+1]—array[n-1]集合中,重複上述步驟

  • 直接選擇排序的排序過程圖示(排升序)

在這裏插入圖片描述

  • 特點:每次只能選出一個最小(最大)的值放到該次排序的第一位

  • 每次執行完排序,則無序數組中元素個數就會少一個.

  • 代碼實現

void Swap(int *a,int *b){
  int tmp=*a;
  *a=*b;
  *b=tmp;
}
void SelectSort(int *array,int size){
	for(int i=0;i<size;i++){
		int min=i;
		for(int j=i+1;j<size;j++){
			if(array[min]>array[j]){
				break;
			}else{
			    min=j;
			}
		}
		Swap(array+min,array+i);
	}
}
  • 直接選擇排序的特性總結
  • 1.直接選擇排序好理解,但是效率低;
  • 2.時間複雜度:O(n^2);
  • 3.空間複雜度:O(1)
  • 4.穩定性:不穩定

直接選擇排序的優化版(一次找到最大最小)

  • 雙向排序,分別找到最小和最大元素
  • 逐漸縮小排序的範圍
void SelectSortXN(int *array,int size){
  int minSpace = 0; //用於存儲最小數的下標
  int maxSpace = size- 1; //用於存放最大數值的下標

  while(minSpace < maxSpace ){
    int min=minSpace;
    int max=minSpace; 

    for(int j=minSpace+1;j<=maxSpace;j++){
      if(array[j]<array[min]){
        min=j;
      }

      if(array[j]>array[max]){
        max=j;
      }
    }
    Swap(array+min,array+minSpace);
    //存在的情況爲minSpace位置的下標即爲最大數的位置下標
    //則會導致相同位置間進行兩次內容交換(其實內部的內容並未改變)
    if(minSpace==max){
      max=min;
    }
    Swap(array+max,array+maxSpace);
    minSpace++;
    maxSpace--;
  }
}
  • 下圖是一次調整後的結果
    在這裏插入圖片描述
  • 注意:再次調整的時候max和min就會重新被調整到minSpace 所指的空間

堆排序

  • 堆排序(HeapSort):就是利用堆積樹(堆)這種數據結構的特性,設計的一種排序算法,它是通過堆來進行數據選擇的.

需要注意:排升序需要建大堆,排降序需要建小堆

  • 排升序的過程圖示

在這裏插入圖片描述

  • 算法思想

  • 學習了堆的知識後,我們發現堆頂(大根堆)的元素是所在數組中最大的元素

  • 利用堆的這個特性將堆中的最後一個元素和堆頂元素進行交換,再繼續向下調整堆,

  • 將所有的元素進行交換和向下調整的過程使得整個數組變的有序

  • 代碼實現

void AdjustDown(int *array,int size,int root){
  while(1){
    int left=2*root+1;
    int max=left;

    if(left>=size){
      return;
    }

    int right=2*root+2;

    if(right<size && array[right] > array[left]){
      max=right; 
    }

    if(array[max] <= array[root]){
      return;
    }

    Swap(array+root,array+ max);
    root=max;
  }
}

void CreateHeap(int *array,int size){
  if(array==nullptr){
    return;
  }

  for(int i=(size-2)/2;i>=0;i--){
    AdjustDown(array,size,i);
  }
}


//建大堆,排升序
void HeapSort(int *array,int size){

  CreateHeap(array,size);
  
  for(int i=0;i<size-1;i++){
    Swap(array,array+size-1-i);
    AdjustDown(array,size-i-1,0);
  }
}

  • 堆排序的特性總結
  • 1.堆排序使用堆來選樹,效率就高很多
  • 2.時間複雜度:O(N*logN)
  • 3.空間複雜度:O(1)
  • 4.穩定性:不穩定
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章