常见排序算法(比较排序)及比较
生活随笔
收集整理的這篇文章主要介紹了
常见排序算法(比较排序)及比较
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#include<iostream>
using?namespace?std;
#include<assert.h>//穩定性:指兩個相同數排序后位置是否變化
//冒泡排序思想:相鄰兩數據比較交換,外層循環控制次數,內層比較??
//void?BubbleSort(int?*a,?size_t?len)
//{
// assert(a);
// for?(size_t?i?=?0;?i?<?len?-?1;?++i)
// {???//相鄰位置數據進行比較,每趟排序都會排出一個最大或最小數
// for?(size_t?j?=?0;?j?<?len?-?i?-?1;?++j)
// {
// if?(a[j]?>?a[j?+?1])
// {
// swap(a[j],?a[j?+?1]);
// }
// }
// }
//}
//
//雞尾酒排序思想:即就是雙向冒泡排序,一趟排序就可以找到一個最大的和最小元素
void?cooktail_sort(int?*arr,?size_t?size)
{assert(arr);int?tail?=?size?-?1;int?i,?j?;for?(i?=?0;?i?<?tail;?++i){for?(int?j?=?tail;?j>i;?--j){if?(arr[j]?<?arr[j?-?1]){swap(arr[j],?arr[j?-?1]);}}++i;for?(j?=?i;?j?<?tail;?++j){if?(arr[j]>arr[j?+?1])swap(arr[j],?arr[j?+?1]);}--tail;}
}
//思想:將當前位置的下一個數據插入到前邊以有序的塊中,再將該數與前邊有序的數據逐一比較。
//每插入一個該位置以前的數據都已有序
//void?InsertSort(int?*a,?size_t?len)//插入排序
//{
// assert(a);
// for?(size_t?i?=?0;?i?<?len-1;?++i)//當i=len-1時,tmp訪問的位置越界
// {
// int?end?=?i;
// int?tmp?=?a[end?+?1];
// while?(end?>=?0?&&?a[end]>tmp)//最后一次進去end=0位置要比
// {
// a[end?+?1]?=?a[end];
// --end;
// }
// a[end?+?1]?=?tmp;
// }
//}
//思想:將一個數組分成兩半,再將每一半分半,遞歸類推,當分出來的只有一個數據時,可認為該小組組內已經有序,然后合并相鄰小組,即先遞歸分解數列,在合并數列
void?Mergesort(int?*arr,?int?begin1,?int?end1,?int?begin2,?int?end2)
{//assert(arr);//if?(begin1?>=?end1?||?begin2?>=?end2)// return;//int?one?=?end1?-?begin1;//int?two?=?end2?-?begin2;//int?*L?=?new?int[one];//開辟兩個數組,一個保存前半部分,一個保存后半部分//int?*R?=?new?int[two];//int?i?=?0,?j?=?0;//for?(;?i?<?one;?++i)//{// L[i]?=?arr[begin1?+?i];//}//for?(i=0;?i?<?two;?++i)//{// R[i]?=?arr[begin2?+?i];//}//int?index?=?begin1;//for?(i?=?0,?j?=?0;?index?<?end2&&i<one&&j<two;?++index)//{// if?(L[i]?<=?R[j])// {// arr[index]?=?L[i];// ++i;// }// else?// {// arr[index]?=?R[j];// ++j;// }//}//if?(i?<?one)//如果一個子序已排完,將剩另一個余的數據直接連接到后邊//{// for?(int?k?=?i;?k?<?one;?++k)// arr[index++]?=?L[k];//}//else//{// for?(int?k?=?j;?k?<two;?++k)// arr[index++]?=?R[k];//}//delete[]?L;//delete[]?R;
}
//void?_merge_sort(int?*arr,?int?begin,?int?end)
//{
// assert(arr);
// if?(begin?+?1?<?end)
// {
// int?mid?=?begin?+?((end?-?begin)?>>?1);
// _merge_sort(arr,?begin,?mid);
// _merge_sort(arr,?mid,?end);
// Mergesort(arr,?begin,?mid,?mid,?end);
// //memcpy(src?+?begin,?dst?+?begin,?(end?-?begin)*sizeof(int));
// }
// else
// return;
//}
//兩個同樣數組,將源數組按序放入目標數組中
void?Mergesort(int?*src,int?*dst,?int?begin1,int?end1,int?begin2,int?end2)
{assert(src&&dst);size_t?index?=?begin1;//兩個同樣大小的數組while?(begin1?<?end1?&&?begin2?<?end2){if?(src[begin1]?<?src[begin2]){dst[index++]?=?src[begin1++];}else{dst[index++]?=?src[begin2++];}}if?(begin1?<?end1){while?(begin1?<?end1){dst[index++]?=?src[begin1++];}}else{while?(begin2?<?end2){dst[index++]?=?src[begin2++];}}
}void?_merge_sort(int?*src,?int?*dst,?int?begin,?int?end)
{assert(src?&&?dst);if?(begin?+?1?<?end){int?mid?=?begin?+?((end?-?begin)?>>?1);_merge_sort(src,?dst,?begin,?mid);_merge_sort(src,?dst,?mid?,?end);Mergesort(src,?dst,?begin,?mid,?mid,?end);memcpy(src?+?begin,?dst?+?begin,?(end?-?begin)*sizeof(int));}elsereturn;
}void?_Merge_sort(int*?src,?size_t?size)
{int*?dst?=?new?int[size];_merge_sort(src,?dst,?0,?size);delete[]?dst;
}//思想:采用分治法思想,選定一個基數,通過一趟排序將要排序的數組一分為二,其中基數前的數據都比它小,基數后的數據都比它大,然后在將這兩部分數據分別進行快排
int?QSort(int?*a,?int?left,?int?right)//快速排序
{assert(a);if?(left?>=?right)return?left;int?key?=?a[right];int?begin?=?left;int?end?=?right-1;while?(begin?<?end){while?(begin?<?end?&&?a[begin]?<=?key)begin++;while?(begin?<?end?&&?a[end]?>?key)end--;if?(begin?<?end)swap(a[begin],?a[end]);}if?(a[end]?>=?a[right])swap(a[end],?a[right]);return?end;
}//void?QuiSort(int*?a,?int??left,?int?right)//挖坑法
//{
// assert(a);
// if?(right?<=?left)
// return;
// int?tmp?=?a[left];
// int?begin?=?left;
// int?end?=?right;
// while?(begin?<?end)
// {
// while?(begin?<?end&&a[end]?>=?tmp)
// end--;
// if?(begin?<?end)
// {
// a[begin++]?=?a[end];
// }
// while?(begin?<?end&&a[begin]?<=?tmp)
// begin++;
// if?(begin?<?end)
// {
// a[end--]?=?a[begin];
// }
// }
// a[begin]?=?tmp;
// QuiSort(a,?left,?begin?-?1);
// QuiSort(a,?begin?+?1,?right);
//}void?QuickSort(int?*a,?int?left,int?right)
{assert(a);if?(left?<?right){int?mid?=?QSort(a,?left,?right);QuickSort(a,?left,?mid?-?1);QuickSort(a,?mid?+?1,?right);}
}//思想:第一次查找最小元素所在位置的下標,與第一個元素交換,之后查找次小元素下標,與第二個元素交換,以此類推
//void?SelectSort(int*?a,?size_t?len)//選擇排序
//{
// assert(a);
// size_t?min_index?;
// for?(size_t?i?=?0;?i?<?len;?++i)
// {
// min_index?=?i;
// for?(size_t?j?=?i+1;?j?<?len?;?++j)
// {
// if?(a[min_index]?>=?a[j])
// {
// min_index?=?j;//找最小元素所在的下標
// }
// }
// swap(a[min_index],?a[i]);//讓最小元素位于第i個位置
// }
//}//思想:將數組按某個增量gap分成若干組,每組中記錄的下標相差gap,對每組中全部元素進行排序??//,然后用一個較小增量再進行上述循環排序,當增量減到1時,整個要排序的數被分成單個組,排序完成
void?Shell_sort(int?*a,size_t?size)
{assert(a);int?gap?=?size?/?3?+?1;while?(1){for?(int?i?=?0;?i?<?size?-?gap;?++i){int?end?=?i;int?tmp?=?a[end?+?gap];while?((a[end]?>?tmp)&&end?>=?0){a[end+gap]?=?a[end];end?-=?gap;}a[end?+?gap]?=?tmp;}if?(gap?==?1)break;gap?=?gap?/?3?+?1;//保證gap最后為1時能執行}
}void?TestSelectSort()
{int?a[10]?=?{?9,?1,?3,?4,?8,?6,?0,?2,?5,?0?};int?len?=?sizeof(a)?/?sizeof(a[0]);cout?<<?"before:";for?(int?i?=?0;?i?<?len;?++i){cout?<<?a[i]?<<?"?";}cout?<<?endl;Shell_sort(a,len);//QuickSort(a,?0,?9);//SelectSort(a,?10);cout?<<?"after:?";for?(int?i?=?0;?i?<?len;?++i){cout?<<?a[i]?<<?"?";}cout?<<?endl;
}
void?TestMergeSort()
{int?a[10]?=?{?9,?1,?3,?4,?8,?6,?7,?2,?5,?0?};int?len?=?sizeof(a)?/?sizeof(a[0]);cout?<<?"before:";for?(int?i?=?0;?i?<?len;?++i){cout?<<?a[i]?<<?"?";}cout?<<?endl;//_merge_sort(a,0,?len);_Merge_sort(a,?len);cout?<<?"after:?";for?(int?i?=?0;?i?<?len;?++i){cout?<<?a[i]?<<?"?";}cout?<<?endl;
}
//堆排序思想:先建成一個大堆或小堆,堆頂元素是最大(最小),讓堆頂元素與最后一個元素交換,數組長度-1,然后向下調整一次,重復上述循環
//template<class?T>
//class?Heap
//{
//public:
// Heap(T*?a,?size_t?size)
// {
// for?(size_t?i?=?0;?i?<?size;?++i)
// {
// _array.push_back(a[i]);
// }
// for?(int?i?=?(_array.size()?-?2)?/?2;?i?>=?0;--i)
// {
// AdjustDown(i,_array.size());
// }
// }
//
// void?AdjustDown(int?root,int?size)
// {
// size_t?lchild?=?2?*?root?+?1;
// while?(lchild?<?size)
// {
// if?((lchild?+?1?<?size)?&&?_array[lchild?+?1]?<?_array[lchild])
// {
// lchild++;
// }
// if?(_array[lchild]?<?_array[root])
// {
// swap(_array[lchild],?_array[root]);
// root=lchild;
// lchild?=?2?*?root?+?1;
// }
// else
// break;
// }
// }
//
// void?AdjustUp(size_t?child)
// {
// size_t?root?=?(child?-?1)?/?2;
// while?(child?>?0)//若root和child為size_t型,永遠都不會小于0,因此不能用它為循環條件
// {
// if?(_array[child]?<?_array[root])
// {
// swap(_array[child],?_array[root]);
// child?=?root;
// root?=?(child?-?1)?/?2;
// }
// else
// break;
// }
// }
//
// void?push_elem(const?T&x)
// {
// _array.push_back(x);
// AdjustUp(_array.size()?-?1);
// }
//
// void?Pop_elem()
// {
// swap(_array[0],?_array[(_array.size()?-?1]));
// _array.pop_back();//將堆頂元素與最后一個元素交換并刪除,再進行向下調整
// AdjustDown(0);
// }
//
// void?Heap_Sort()
// {
// int?size?=?_array.size();
// while?(size>0)
// {
// swap(_array[0],?_array[size-1]);
// cout?<<?_array[size?-?1]?<<?"?";
// //_array.pop_back();
// AdjustDown(0,size-1);
// --size;
// }
// }
// void?Display()
// {
// cout?<<?"heap?is:";
// for?(int?i?=?0;?i?<?_array.size();?++i)
// {
// cout?<<?_array[i]?<<?"?";
// }
// cout?<<?endl;
// }
//protected:
// vector<T>?_array;
//
//};
//
算法的適用場景及比較:
比較排序:(1)插入(直接插入、希爾排序)、(2)選擇(選擇排序、堆排序)、(3)交換(冒泡排序、快排)(4)外排序(歸并)
1)時間復雜度:
平均性能為O(N^2):插入、選擇、冒泡
數據規模小時:直接插入排序較好
數據規模大時:冒泡排序時間代價最高
平均性能為O(NlgN):堆、快速、歸并
數據規模大時:適用堆排序(例:在一千萬個數中找最小的前100個數)
數據規模小時:快速排序較好,當小到一定區間使用插入排序
希爾排序平均時間復雜度為O(N^1.3)
穩定性指的是兩個相同的數排序后位置是否變化,若無變化則穩定
2).穩定性分析:
穩定:冒泡、插入、歸并
不穩定:選擇、希爾、堆、快排
轉載于:https://blog.51cto.com/10541559/1773689
總結
以上是生活随笔為你收集整理的常见排序算法(比较排序)及比较的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jenkins部署java项目之小白的笔
- 下一篇: Hadoop学习笔记(七)