七大排序
不廢話,直接上代碼,註釋分明,思路清晰。
sortingmethod.h
#ifndef SORTINGMETHOD_H
#define SORTINGMETHOD_H
#include <iostream>
#define SORTTYPE int
using namespace std;
/**
* insert sort
*/
/*direct insert sort*/
void direct_insert_sort( SORTTYPE *arr,int len);
/*shell sort*/
void shell_sort(SORTTYPE *arr,int len);
/**
* select sort
*/
/*simple select sort*/
void simple_select_sort( SORTTYPE *arr ,int len);
/*heap sort*/
void heap_sort(SORTTYPE *arr,int len);
void adjust_max_heap(SORTTYPE *arr, int len,int i);
void build_max_heap(SORTTYPE *arr , int len);
/**
* exchange sort
*/
/*bubble sort*/
void bubble_sort( SORTTYPE *arr ,int len);
/*fast sort*/
void quick_sort(SORTTYPE *arr , int start, int end);
/**
* merge sort
*/
void merge_merge_sort(SORTTYPE *arr , int first, int mid ,int last , SORTTYPE *temp);
void devide_merge_sort(SORTTYPE *arr , int first, int last , SORTTYPE *temp);
void merge_sort(SORTTYPE *arr, int len);
/*show element*/
void show_element(SORTTYPE *arr , int len);
#endif // SORTINGMETHOD_H
sortingmethod.cpp
#include "sortingmethod.h"
/*
* All sorting is from min to max
*/
/**
* insert sort
*/
/*direct insert sort*/
void direct_insert_sort( SORTTYPE *arr,int len){
int temp ,i=0,j=0; /*temp暫存arr[i]*/
for(i = 1 ; i < len ; i++){
/*對每一個arr[i]~arr[0]的數*/
temp = arr[i];
for(j=i ; j>0 ; j -- ) {
/*當arr[j-1]比tem大時,向右移動一個位置*/
if ( arr[j-1] > temp ){
arr[j] = arr[j-1];
}
else
break;
}
/*此時j剛好爲重複的那個數字*/
arr[j] = temp;
}
// for(i = 1; i<len ; i++){
// temp = arr[i];
// for(j = i-1 ; j > -1 ; j--){
// if(arr[j]>temp){
// arr[j+1] = arr [j];
// }
// else
// break;
// }
// arr[j+1] = temp;
// }
}
/*shell sort*/
void shell_sort(SORTTYPE *arr,int len){
/*
* 將待排序數組按照步長gap進行分組,然後將每組的元素利用直接插入排序的方法進行排序;
* 每次將gap折半減小,循環上述操作;
* 當gap=1時,利用直接插入,完成排序。
*/
int i=0,j=0,k=-1,temp=-1;
int gap = len / 2; /*初始化gap,一般時len的一半*/
while( gap >= 1 ){
for( i = gap ; i < len ; i+=gap ){
k = i; temp = arr[k];
for( j = i - gap ; (j >= 0)&&(arr[j] >temp); j -=gap ){
arr[j+gap] = arr[j];
k = j;
}
arr[k] = temp;
}
gap /=2;
}
}
/**
* select sort
*/
/*simple select sort*/
void simple_select_sort( SORTTYPE *arr ,int len){
/*
簡單選擇排序的基本思想:比較+交換。
從待排序序列中,找到關鍵字最小的元素;
如果最小元素不是待排序序列的第一個元素,將其和第一個元素互換;
從餘下的 len - 1 個元素中,找出關鍵字最小的元素,重複(1)、(2)步,直到排序結束。
因此簡單選擇排序也是通過兩層循環實現。
第一層循環:依次遍歷序列中的每一個元素
第二層循環:將遍歷得到的當前元素依次與餘下的元素進行比較,符合最小元素的條件,則交換。
*/
int i=0,j=0,k=0,min,tem;
for(i=0; i < len ; i++ ){
min = arr[i];
/*下面這個循環找到本輪的最小值和下標*/
for(j = i+1 ; j < len ; j++){
if(arr[j] < min){
min = arr[j];
k = j;
}
}
/*如果arr[i]>min則需要交換*/
if(arr[i] > min){
tem= arr[i];
arr[i] = arr[k];
arr[k] = tem;
}
}
}
/*heap sort*/
/*
堆排序按照以下步驟完成:
1.首先將序列構建稱爲大頂堆;
(這樣滿足了大頂堆那條性質:位於根節點的元素一定是當前序列的最大值
2.取出當前大頂堆的根節點,將其與序列末尾元素進行交換;
(此時:序列末尾的元素爲已排序的最大值;由於交換了元素,當前位於根節點的堆並不一定滿足大頂堆的性質)
3.對交換後的n-1個序列元素進行調整,使其滿足大頂堆的性質;
4.重複2.3步驟,直至堆中只有1個元素爲止
*/
/* 調整大頂堆 */
void adjust_max_heap(SORTTYPE *arr, int len,int i){
/*
* arr:待調整序列
* len: 序列長度
* i:需要調整的結點
*/
/*定義一個int值保存當前序列最大值的下標*/
int largest = i; int left,right;
/*執行循環操作任務:1.尋找最大值的下標;2.最大值與父節點交換*/
while (1) {
/*獲得序列左右葉子節點的下標*/
left = i*2+1; right = i*2+2;
/*當左葉子節點的下標小於序列長度 並且 左葉子節點的值大於父節點時,將左葉子節點的下標賦值給largest*/
if(left < len && arr[left] > arr[largest]){
largest = left;
}else{
largest = i;
}
/*當右葉子節點的下標小於序列長度 並且 右葉子節點的值大於父節點時,將右葉子節點的下標值賦值給largest*/
if(right < len && arr[right] > arr[largest])
largest = right;
/*如果largest不等於i 說明當前的父節點不是最大值,需要交換值*/
int temp;
if(largest != i){
temp = arr[i];
arr[i] = arr[largest];
arr[largest] = temp;
i = largest;
continue;
}else{
break;
}
}
}
/*建立大頂堆*/
void build_max_heap(SORTTYPE *arr , int len){
for( int i = (len-1)/2; i>-1; i-- ){
adjust_max_heap(arr,len,i);
}
}
/* 堆排序 heap_sort */
void heap_sort(SORTTYPE *arr,int len){
/*先建立大頂堆,保證最大值位於根節點;並且父節點的值大於葉子結點*/
build_max_heap(arr , len);
/* i = 當前堆中序列的長度.初始化爲序列的長度*/
int i = len;
/*執行循環:1. 每次取出堆頂元素置於序列的最後(len-1,len-2,len-3...)
2. 調整堆,使其繼續滿足大頂堆的性質,注意實時修改堆中序列的長度*/
int temp;
while( i > 0){
temp = arr[i-1];
arr[i - 1] = arr[0];
arr[0] = temp;
/*堆中序列長度減1*/
i-=1;
/*調整大頂堆*/
adjust_max_heap(arr , i , 0);
}
}
/**
* exchange sort
*/
/*bubble sort*/
void bubble_sort( SORTTYPE *arr ,int len){
int temp;
for(int i =0 ; i < len ; i++ ){
for(int j = len-1; j>i ; j --){
if (arr[j] < arr[j-1]){
temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp;
}
}
}
}
/*quick sort*/
void quick_sort(SORTTYPE *arr ,int start,int end){
/*快速排序的基本思想:挖坑填數+分治法
從序列當中選擇一個基準數(pivot ,這裏選擇序列當中第一個數最爲基準數)
將序列當中的所有數依次遍歷,比基準數大的位於其右側,比基準數小的位於其左側
重複步驟1.2,直到所有子集當中只有一個元素爲止。
用僞代碼描述如下:
1.i =left; j = right; 將基準數挖出形成第一個坑a[i]。
2.j--由後向前找比它小的數,找到後挖出此數填前一個坑a[i]中。
3.i++由前向後找比它大的數,找到後也挖出此數填到前一個坑a[j]中。
4.再重複執行2,3二步,直到i==j,將基準數填入a[i]中
*/
int i, j ,pivot;
if (start <end){
i = start;
j = end;
pivot = arr[start];
}
else
return; /*注意這個地方容易忘*/
while(i < j){
/*從右開始向左尋找第一個小於pivot的值*/
while(i < j && arr[j] >= pivot)
j-=1;
/*將小於pivot的值移到左邊*/
if(i < j){
arr[i] = arr[j];
i+=1;
}
/*從左開始向右尋找第一個大於pivot的值*/
while (i < j && arr[i] <= pivot)
i+=1;
/*將大於pivot的值移到右邊*/
if(i<j){
arr[j] = arr[i];
j-=1;
}
}
/*循環結束後,說明 i=j,此時左邊的值全都小於pivot,右邊的值全都大於pivot*/
arr[i]=pivot;
show_element(arr,14);
/*pivot的位置移動正確,那麼此時只需對左右兩側的序列調用此函數進一步排序即可*/
/*遞歸調用函數:依次對左側序列:從0 ~ i-1//右側序列:從i+1 ~ end*/
quick_sort(arr,start,i-1);
cout<<"left is all right"<<endl;
quick_sort(arr,i+1,end);
}
/**
* merge sort
*/
/*
* merge_sort
* 歸併排序的函數
*/
void merge_sort(SORTTYPE *arr,int len){
/*
歸併排序是建立在歸併操作上的一種有效的排序算法,該算法是採用分治法的一個典型的應用。
它的基本操作是:
將已有的子序列合併,達到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。
歸併排序要做兩件事:
分解----將序列每次折半拆分
合併----將劃分後的序列段兩兩排序合併
因此,歸併排序實際上就是兩個操作,拆分+合併
如何合併?
arr[first...mid]爲第一段,arr[mid+1...last]爲第二段,並且兩端已經有序,現在要將兩端合成達到arr[first...last]並且也有序。
(1)依次從第一段與第二段中取出元素比較,將較小的元素賦值給temp[]
(2)重複執行上一步,當某一段賦值結束,則將另一段剩下的元素賦值給temp[]
(3)此時將temp[]中的元素複製給arr[],則得到的arr[first...last]有序
如何分解?
(1)採用遞歸的方法,首先將待排序列分成A,B兩組;
(2)重複對A、B序列分組;
(3)直到分組後組內只有一個元素,此時認爲組內所有元素有序,分組結束。
*/
SORTTYPE temp[len];
/*調用歸併排序*/
devide_merge_sort(arr, 0 , len-1 , temp);
}
void merge_merge_sort(SORTTYPE *arr , int first, int mid , int last , int *temp){
/*合併的函數----將序列arr[first...mid]與序列arr[mid+1...last]進行合併*/
int i = first, j = mid +1 ,k = 0;
/*當左右兩邊都有數時進行比較,取較小的數*/
while(i <= mid && j <= last){
if( arr[i] <= arr[j])
temp[k++] = arr[i++];
else
temp[k++] = arr[j++];
}
/*如果左邊序列還有數*/
while(i <= mid)
temp[k++] = arr[i++];
/*如果右邊序列還有數*/
while(j <= last)
temp[k++] = arr[j++];
/*將temp當中該段有序元素賦值給L待排序列使之部分有序*/
for(int x = 0; x < k ; x++)
arr[first + x] = temp[x];
}
/*這是分組的函數*/
void devide_merge_sort(SORTTYPE *arr , int first, int last , SORTTYPE *temp){
int mid;
if(first < last){
mid = (first + last)/2;
/*使左邊序列有序*/
devide_merge_sort(arr, first ,mid ,temp);
/*使右邊序列有序*/
devide_merge_sort(arr, mid+1 , last ,temp);
/*將兩個有序序列合併*/
merge_merge_sort(arr, first ,mid , last,temp);
show_element(arr , 14);
}
}
/*show element*/
void show_element(SORTTYPE *arr , int len){
for(int i = 0; i < len ; i++ ){
SORTTYPE tem = arr[i];
cout<<tem<<" ";
}
cout<<'\n';
}
main.cpp
#include <iostream>
#include "sortingmethod.h"
using namespace std;
int main()
{
SORTTYPE arr[] = {8,1,13,7,3,12,4,6,2,14,5,9,11,10};
int len = 14;
show_element(arr, len);
// direct_insert_sort(arr,len);
// bubble_sort(arr , len);
// shell_sort(arr,len);
// simple_select_sort(arr,len);
// heap_sort(arr , len);
// quick_sort(arr,0,13);
// merge_sort(arr,len);
cout<<"sort ending!"<<endl;
show_element(arr, len);
return 0;
}