文章目錄
閱讀代碼是件非常枯燥的事,所以儘量每一行都加的註釋,方便閱讀理解。
六、排序
(一)插入類排序
1、直接插入排序
/*
method:
直接插入排序法
param:
disorder_sqc 無序序列
num 無序序列的長度
*/
int Insert_Direct(int disorder_sqc[], int num)
{
int i = 0,j = 0;
int temp = 0; //臨時變量
for (i = 1; i < num; ++i) //i=1,默認前面已經有一個元素是有序的
{
temp = disorder_sqc[i]; //獲取當前值
j = i - 1; //獲取當前下標
while (j >= 0 && temp < disorder_sqc[j]) //從當前下標往前依次判斷
{
disorder_sqc[j + 1] = disorder_sqc[j]; //當前位置元素如果比待插入值大,往後移動一個元素,給插入值騰地方
--j;
}
disorder_sqc[j+1] = temp; //插入值
}
}
2、折半插入排序
/*
method:
折半插入排序法
param:
order_sqc 無序序列
num 無序序列的長度
*/
void Half_Insert(int disorder_sqc[], int num)
{
int i = 0;
int temp = 0;
int low = 0, high = 1, mid = 0,final_ = 0; //final_指向最終插入的位置
if (disorder_sqc[0] > disorder_sqc[1]) //默認是升序排序,如果前兩個不是升序,交換位置
{
temp = disorder_sqc[1];
disorder_sqc[1] = disorder_sqc[0];
disorder_sqc[0] = temp;
}
for (i = 2; i < num; ++i)
{
low = 0;
high = i - 1; //因爲有序數組在插入過程中不斷的邊長,所以high跟着變
temp = disorder_sqc[i]; //temp獲取要插入值的臨時變量
if (disorder_sqc[i] > disorder_sqc[high]) //如果大於最大的,則不用排序
final_ = i; //直接插入到最後
else if (disorder_sqc[i] < disorder_sqc[low]) //如果小於最小的,直接放在最前方
final_ = 0;
else
{
while (low <= high) //以low<high爲判斷標準
{
mid = (low + high) / 2; //mid 因爲int型,向下取整
if (disorder_sqc[mid] > temp) //如果該位置的值大於要插入的值
high = mid - 1; //說明值在mid位置的左邊,默認爲升序排序
else
low = mid + 1; //否則在mid位置的右邊,默認爲升序排序
}
final_ = low; //最後獲取low的位置,即爲插入的值
}
for (int j = i - 1; j >= final_; --j) //將要插入位置之後的元素依次往後挪一位
{
disorder_sqc[j + 1] = disorder_sqc[j]; //往後移動元素
}
disorder_sqc[final_] = temp; //插入到該位置
}
}
3、希爾排序
/*
method:
Shell排序法
param:
order_sqc 無序序列
num 無序序列的長度
*/
void Shell_Sort(int disorder_sqc[], int num)
{
int sub_num = 0; //子序列元素數量
int increment = num / 2; //初始值,增量爲元素一半
int sub_sequence[MAXSIZE][MAXSIZE];
while (increment) //增量每次除以2,等於0退出,則排序完成
{
for (int i = 0; i < num; ++i)
{
for (int j = i, k = 0; j < num; j += increment) //根據增量來取值
{
sub_sequence[i][k++] = disorder_sqc[j]; //取出來多個子序列
sub_num = k;
}
Insert_Direct(sub_sequence[i], sub_num); //取出來一組排序一組
}
increment = increment / 2; //縮小增量
}
for (int i = 0; i < num; i++)
{
disorder_sqc[i] = sub_sequence[0][i]; //將子序列排序號的元素賦值給原數組
}
}
(二)交換類排序
1、冒泡排序
/*
method:
冒泡排序
param:
disorder_sqc 無序序列
num 無序序列的長度
*/
void Bubble_Sort(int disorder_sqc[], int num)
{
int temp = 0; //交換時候的中間變量
int flag = 0; //判斷是否發生交換
for (int j = num - 1; j > 0; --j) //每次循環完一遍之後,保留最大值
{
flag = 0;
for (int i = 0; i < j; ++i)
{
if (disorder_sqc[i] > disorder_sqc[i + 1]) //如果前面的元素大於後面的
{
flag = 1; //交換標誌位
temp = disorder_sqc[i + 1]; //交換前後值
disorder_sqc[i + 1] = disorder_sqc[i];
disorder_sqc[i] = temp;
}
}
if (flag == 0) //如果循環一遍之後,未發生交換,則排序完成
break;
}
}
2、快速排序
/*
method:
快速排序
param:
disorder_sqc 無序序列
low 無序序列的最小位置下標
high 無序序列的最大位置下標
*/
void Quick_Sort(int disorder_sqc[],int low,int high)
{
int temp = 0; //取出要比較的值,也就是樞軸
int i = low, j = high; //將檢測low-high範圍內的值
if (low < high) //序列範圍
{
temp = disorder_sqc[low]; //取序列的第一個值,作爲樞軸,也就是要比較的值
while (i < j) //如果i<j,則序列內存在未操作的元素
{
while ((i < j)) //判斷序列內還有未操作的元素,先由後往前查詢
{
if (disorder_sqc[j] < temp) //直到檢測到一個值小於樞軸
{
disorder_sqc[i] = disorder_sqc[j]; //將該位置存放小於樞軸的值
++i; //左側範圍向後挪一位
break; //這裏要退出,避免操作後範圍,
}
--j; //如果經過上方break,則不操作這個
}
while (i < j) //判斷序列內還有未操作的元素
{ //查詢順序發生變化,從前往後查詢
if (disorder_sqc[i] > temp) //直到查詢到一個大於樞軸的值
{
disorder_sqc[j] = disorder_sqc[i]; //放到之前右邊範圍的位置
--j; //右範圍往前挪一位
break; //退出
}
++i; //如果經過上方break,則不操作這個
}
}
disorder_sqc[i] = temp; //此時i=j,就是樞軸插入的位置
//上面while循環之後,即爲一次樞軸比較,比樞軸小的元素都在左邊,比其大的元素都在右邊
Quick_Sort(disorder_sqc, low, i - 1); //按照相同操作 樞軸左邊的序列
Quick_Sort(disorder_sqc, i + 1, high); //按照相同操作 樞軸右邊的序列
}
}
(三)選擇類排序
1、簡單選擇排序
/*
method:
簡單選擇排序
param:
disorder_sqc 無序序列
num 無序序列的長度
*/
void Select_Sort(int disorder_sqc[], int num)
{
int min_sub = 0; //存放最小值的下標
int temp = 0; //中間值
int i = 0, j = 0; //用於循環
for (i = 0; i < num; ++i) //循環n次
{
min_sub = i; //獲取第一個元素的下標
for (j = i+1 ; j < num ; ++j) //執行一趟,選擇出來一個最小值
{
if (disorder_sqc[min_sub] > disorder_sqc[j]) //得到最小值下標
min_sub = j; //得到最小值的下標
}
temp = disorder_sqc[min_sub]; //將最小值與第一個元素互換位置
disorder_sqc[min_sub] = disorder_sqc[i];
disorder_sqc[i] = temp;
}
}
2、堆排序
- 調整堆函數
/*
method:
將數組中low-high位置範圍內,對low上的結點進行調整,使其爲最大
param:
disorder_sqc 無序序列
low 無序序列的最小位置下標
high 無序序列的最大位置下標
*/
void Shift(int disorder_sqc[], int low, int high)
{
int i = low;
int j = 2 * i; //j是i的孩子結點
int temp = disorder_sqc[i]; //temp表示雙親結點的值
while (j <= high)
{
if ((j<high) && (disorder_sqc[j] < disorder_sqc[j + 1])) //如果右孩子大
{
++j; //將j指向右孩子
}
if (temp < disorder_sqc[j]) //比較雙親結點與孩子結點的大小,如果孩子結點的值大,進行交換
{
disorder_sqc[i] = disorder_sqc[j]; //將disorder_sqc[j]調整到雙親結點位置上
i = j; //修改i,j值,使其繼續向下調整
j = 2 * i;
}
else
break;
}
disorder_sqc[i] = temp; //將調整的值放在最終位置
}
- 排序函數
/*
method:
堆排序
param:
disorder_sqc 無序序列
num 無序序列的長度
//注意:這裏將根結點作爲數組的[1]下標,可改爲零,並且一定要更改找左右孩子結點的公式
*/
void Heap_Sort(int disorder_sqc[], int num)
{
int i = 0;
int temp = 0;
for (i = num / 2; i >= 1; --i) //建立初始堆,這裏的除以2,是爲了按層進行操作 因爲每層結點數爲2的冪
{
Shift(disorder_sqc, i, num); //由下往上進行調整,確保有序,
}
for (i = num; i >= 2; --i) //爲了換出根結點的值,將其放入最終位置
{
temp = disorder_sqc[1]; //取出最大值
disorder_sqc[1] = disorder_sqc[i];
disorder_sqc[i] = temp; //將最大值交換到最後一個
Shift(disorder_sqc, 1, i - 1); //將交換之後的堆再次進行排序
}
}
(四)歸併類排序
1、二路歸併排序(merge sort)
/*
method:
二路歸併排序
param:
disorder_sqc 無序序列
low 無序序列的最小位置下標
high 無序序列的最大位置下標
*/
void Merge_Sort(int disorder_sqc[], int low, int high)
{
if (low < high)
{
int mid =(low + high) / 2; //每次縮小組的大小
Merge_Sort(disorder_sqc, low, mid); //將其分爲多個組,先是一個一組,然後兩個一組,四個一組,一次類推
Merge_Sort(disorder_sqc, mid + 1, high);
Quick_Sort(disorder_sqc, low, high); //這裏是直接進行了快速排序,直接將組內值進行排序
}
}
(五)基數排序
/*
method:
基數排序,比較數字
param:
disorder_sqc 無序序列
num 無序序列的長度
*/
void Base_Sort(int disorder_sqc[], int num)
{
int k = 0;
int max_bit = 0,temp = 0; //獲取最高位
int subscript = 0; //存放某一位的值,下標
int calculate_time = 1; //分配和收集的次數,也就是全部元素往桶裏放的次數
int barrel[MAXSIZE][MAXSIZE] = {0}; //建立桶,用來存放相同位的數組
for (int i = 0; i < num; ++i)
{
temp = log(disorder_sqc[i]) / log(10);
if (temp > max_bit)
max_bit = temp; //取最高位
}
while (1)
{
for (int i = 0; i < num; ++i) //遍歷要排序的元素
{
k = 0;
subscript = disorder_sqc[i] / calculate_time % 10; //獲取最低位的值
while (barrel[subscript][k]) k++; //直到判斷k不爲零
barrel[subscript][k] = disorder_sqc[i]; //往桶裏放值
}
k = 0; //將k清零,用於取值
for (int i = 0; i < MAXSIZE; ++i) //取出桶內的值
{
for (int j = 0; j < MAXSIZE; ++j)
{
if (barrel[i][j] == 0) //如果桶內值爲0,說明桶內值已取完
break;
disorder_sqc[k++] = barrel[i][j]; //取值
barrel[i][j] = 0; //取完值後清零,避免干擾
}
}
calculate_time *= 10; //依次向高位比較
if (calculate_time > pow(10.0, max_bit))
break;
}
}