您好,登錄后才能下訂單哦!
#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)); } else return; } 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).穩定性分析:
穩定:冒泡、插入、歸并
不穩定:選擇、希爾、堆、快排
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。