//*************************************************************************************************************************
***2019年11月25日22:25:51
***這是一個學習的過程!!!
***參考了以下博客,寫的很詳細!!!
***十大排序算法(C++實現): https://blog.csdn.net/mengyujia1234/article/details/90179896
***輕鬆搞定十大排序算法(c++版):https://blog.csdn.net/opooc/article/details/80994353
***史上最容易理解的《十大經典算法(動態圖展示)》:https://blog.csdn.net/wfq784967698/article/details/79551476
***有前人的基礎,我纔有更深層的理解!!!
***以下都是經過自己編譯器實現了的,做個簡單的mark!!!
//**************************************************************************************************************************
/*****************************插入排序*******************************************/
void insertSort(int arr[],int len)
{
//插入排序的思想:
/*從第一個元素開始,去除下一個元素,在已經排序的元素中從後向前掃描,如果前的元素大於該元素,
* 就將其向後移動以爲,直到找到位置
* */
for (int i = 1; i < len;i++)
{
int preindex;
int current = arr[i];
for ( preindex = i - 1;preindex >=0 && arr[preindex] > current;preindex -- ) //找位置
{
//前面的大於當前元素
arr[preindex + 1 ] = arr[preindex]; //將前面的向後移動一位
}
//位置找到了,交換
arr[preindex + 1] = current;
}
}
/*****************************希爾排序*******************************************/
void shellSort(int arr[],int len)
{
int gap,i,current,preindex;
for(gap = len / 2; gap > 0 ; gap = gap / 2) //控制增量
{
for(i = gap; i < len; i ++) //裏面就是一個插入排序
{
current = arr[i];
for(preindex = i - gap;
preindex >=0 && current <arr[preindex];
preindex = preindex - gap
) //比較大小值
{
arr[preindex +gap ] = arr[preindex];
}
arr[preindex + gap] = current;
}
}
}
/*****************************冒泡排序*******************************************/
void bubleSort(int arr[],int len)
{
int temp=0;
for (int first = 0;first <len -1;first ++)
{
for (int last = len - 1;last >= first;last --)
{
if(arr[last+1 ] < arr[last]) //後面一個比前面一個小,遵循曉得向前跑
{
temp = arr[last];
arr[last] = arr[last+1];
arr[last+1] = temp;
}
}
}
}
void bubleUpdateSort(int arr[],int len)
{
int temp=0;
for (int first = 1;first <len;first ++) //控制趟數
{
int flag = 0 ; //標誌位,
for (int last = 0;last <len - first;last ++) //控制交換次數
{
if(arr[last+1 ] < arr[last]) //後面一個比前面一個小,遵循小的向前跑
{
temp = arr[last];
arr[last] = arr[last+1];
arr[last+1] = temp;
flag = 1;
}
}
if(flag == 0) //說明這個沒有交換,是有序的
{
return;
}
}
}
/*****************************快速排序*******************************************/
void quickSort(int arr[],int low,int high) //書上的,不能很好的理解
{
int left,right,pivot;
if(low < high)
{
pivot = arr[low]; //選擇基準
left = low;
right = high;
while (left < right)
{
while (left < right && arr[right] >= pivot)//找不滿足條件的值,然後停止
{
right --;
}
if(left < right)
{
arr[left++] = arr[right];
}
while (left < right && arr[left] <= pivot)//找不滿足條件的值,然後停止
{
left ++;
}
if(left < right)
{
arr[right--] = arr[left];
}
arr[left] = pivot; //基準進行歸爲
quickSort(arr,low,left-1);
quickSort(arr,left+1,high);
}
}
}
void quick_Sort(int arr[],int left, int right) //來自網上,比較容易理解
{
int i, j, t, temp;
if(left > right)
{
return;
}
temp = arr[left]; //temp中存的就是基準數
i = left;
j = right;
while(i != j) //這個是第一遍,完了之後用遞歸執行已經有序的區間,知道全部有序
{
//順序很重要,要先從右邊開始找
while(arr[j] >= temp && i < j)
j--;
while(arr[i] <= temp && i < j)//再找右邊的
i++;
if(i < j)//交換兩個數在數組中的位置
{
t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
//最終將基準數歸位
arr[left] = arr[i];
arr[i] = temp;
quick_Sort(arr,left, i-1);//繼續處理左邊的,這裏是一個遞歸的過程
quick_Sort(arr,i+1, right);//繼續處理右邊的 ,這裏是一個遞歸的過程
}
/*****************************選擇排序*******************************************/
void selectSort(int arr[],int len)
{
//每次選擇最小的數 並標記其位置
for(int i = 0;i < len; i++)
{
int min=arr[i]; //默認當前爲最小
int location = i; //默認標記當前位置
for(int j = i;j < len; j++)
{
if(arr[j] < min) //如果比min還小,則這個數爲最新的最小值,要保存起來,並標記
{
min = arr[j];
location = j;
}
}
//遍歷完之後 在將arr[i]和最小值進行交換
arr[location] = arr[i];
arr[i] = min;
}
}
/*****************************堆排序*******************************************/
void heapSwap(int *a,int *b)
{
//使用這個將數組的第一個和最後一個元素進行交換
int temp;
temp = *a;
*a= *b;
*b = temp;
}
void max_heapify(int arr[], int start, int end)
{
//建立父節點指標和子節點指標
int dad = start;
int son = dad * 2 + 1;
while (son <= end) //若子節點指標在範圍內才做比較
{
if (son + 1 <= end && arr[son] < arr[son + 1])
{
//先比較兩個子節點大小,選擇最大的
son++;
}
if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數
{
return;
}
else //否則交換父子內容再繼續子節點和孫節點比較
{
heapSwap(&arr[dad], &arr[son]);
dad = son;
son = dad * 2 + 1;
}
}
}
void heap_sort(int arr[], int len)
{
int i;
//初始化,i從最後一個父節點開始調整
for (i = len / 2 - 1; i >= 0; i--)
{
max_heapify(arr, i, len - 1);
}
for (i = len - 1; i > 0; i--)
{
heapSwap(&arr[0], &arr[i]); //交換,再重新調整,直到排序完畢
max_heapify(arr, 0, i - 1); //再重新調整,直到排序完畢
}
}
/*****************************歸併排序*******************************************/
void merge(int array[],int temp[],int leftpos,int rightpos,int rightEnd) //將結果進行排序
{
//這個函數主要是在將有序的數進行合併
int temppos = leftpos; //臨時的temp數組中的索引
int leftEnd= rightpos - 1; //左邊的末尾端
int arraylen = rightEnd -leftpos + 1; //這個是整個數組的長度
while (leftpos <= leftEnd &&rightpos <= rightEnd) //只要這個條件滿足,就一直比較左右兩邊值的大小
{
if(array[leftpos] < array[rightpos])
{
temp[temppos++] = array[leftpos++]; //左邊的小
}
else {
temp[temppos++] = array[rightpos++]; //右邊的小
}
}
//這樣一來,後面的就是剩下的,
while (leftpos <= leftEnd)
{
temp[temppos++] = array[leftpos++]; //把左邊剩餘元素全部放進去
}
while (rightpos <= rightEnd)
{
temp[temppos++] = array[rightpos++]; //把右邊的剩餘元素全部放進去
}
//這樣一來,所有的元素全都在temp臨時數組中排序完成,現在要賦值給原來的數組
for (int i=0;i<arraylen;i++,rightEnd--)
{
array[rightEnd] = temp[rightEnd];
}
}
void mergerecursive(int array[],int temp[],int low,int high) //局部函數調用
{
if(low>=high)
{
return;
}
//計算分裂點
int middle= (low+high)/2;
mergerecursive(array,temp,low,middle); //把子區間[low,middle]遞歸併排序
mergerecursive(array,temp,middle+1,high); //吧把子區間[middle+1,high]遞歸併排序
merge(array,temp,low,middle+1,high); //組合,吧兩個有序區間組合爲一個有序區間
}
void mergeSort(int array[],int len) //整體函數調用
{
//我要歸併排序,兩個比較
int *tmp = NULL;
tmp = new int [len];
if(tmp!=NULL)
{
mergerecursive(array,tmp,0,len-1);
delete tmp;
}
}
/*****************************基數排序*******************************************/
int findMax(int array[], int len)
{
//這個是爲了查找要排序中最大的位數
int max = 0;
int count = 1;
int temp; //temp來存儲位數
for(int i = 0; i <len; i++)
{
while ((temp/10) != 0)
{
temp = array[i] / 10;
count ++;
}
if(count > max)
{
max = count;
}
}
return max; //返回的是最大的位數
}
void baseSort(int array[] ,int len)
{
int *count = new int[10]; //計數器
int *temp = new int [len]; //一個桶能裝多少數據
int maxbit = findMax(array,len); //先獲得最大位數,最大的位數就是需要排序的次數
for(int i;i < maxbit;i++) //比較的次數
{
//清空桶中的數據
for(int i = 0; i < 10; i++)
{
count[i] = 0;
}
//清空
}
}
void printSort(int arr[],int len)
{
for(int j = 0 ;j < len; j++)
{
cout << " "<<arr[j];
}
cout <<endl;
}
int main()
{
int array[]={10,9,8,7,6,5,4,3,2,45,58,54,56,8,415,1,5,15,898,545,6,5,4,3,2,1,0,10,9,8,7,6,5,4,3,2,1,0};
int len = sizeof (array)/sizeof (array[0]);
// bubleSort(array,len);
// bubleUpdateSort(array,len);
// shellSort(array,len);
// insertSort(array,len);
// quick_Sort(array,0,9);
// selectSort(array,len);
// quickSort(array,0,5);
// heap_sort(array,len);
mergeSort(array,len);
printSort(array,len);
return 0;
}