排序算法:快排,插入,希尔,归并,堆,选择,冒泡
#include <iostream> using namespace std; //划分函数:将数组划分为大于和小于某元素的两部分 template <typename T> int partition_job(T *array, int left, int right) { int index = left; int pivot = array[index]; swap(array[index],array[right]); for(int i = left; i< right; i++) { if(array[i] > pivot) { swap(array[index++], array[i]); }//降序 } swap(array[right], array[index]); return index; } //快速排序:分治法+挖空填空 //快速排序的平均时间复杂度为:O(nlog(n)),每次划分数组整体比较n次,分成两半。 template <typename T> void qsort_job(T *array, int left, int right) { if(left >= right) return ; int index = partition_job(array, left, right); qsort_job(array, left, index - 1);//做部分 qsort_job(array, index + 1, right); } //插入排序 //平均时间复杂度:O(n2);最好O(n):已排好序;最差O(n2):完全逆序。 /* 原理: 初始:首个元素自成一个有序(已排)序列,其余的记录为无序(待排)序列。 循环:从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中。 终止:直至最后一个记录插入到有序序列中为止。 */ template <typename T> void insertsort_job(T *data, int size) { for(int i = 1; i < size; i++) { T key = data[i]; int j(i-1); for(; j >= 0 && data[j] > key; j--) //降序 data[j+1] = data[j]; data[j+1] = key; } } //希尔排序:有间隔的插入排序,间隔逐渐减小,最后间隔为1 //不稳定的, template <typename T> void shellsort_job(T *data, size_t size) { for(int gap = size/2; gap > 0; gap /= 2) { for(int i = gap; i < size; ++i) { T key = data[i]; int j = 0; for(j = i - gap; j >= 0 && data[j] > key; j -= gap) //降序 data[j+gap] = data[j]; data[j+gap] = key; } } } //归并排序 //时间复杂度:O(nlog(n)),取n次堆顶元素,并维护n次堆,每次维护时间为O(log(n)) /* 初始化:将整个序列建立成一个堆。 循环:堆顶元素(最值)与最后一个元素互换,堆的最后一个元素即为最大(以大顶堆为例)记录,完成一次排序 接着将前N-1个元素(即不包括最大记录)进行大顶堆维护,再将堆顶元素与最后一个元素互换,得到次大值。 重复以上步骤,直至堆中只剩一个记录,排序结束。 */ template <typename T> void Merge(T *array, int low, int mid, int high) { int i, j, k; T *temp = (T *)malloc((high - low + 1) * sizeof(T)); i = low, j = mid + 1, k = 0; while(i <= mid && j <= high) //合并已排好序的前后两半数组元素,以mid为中点分割。 { if(array[i] < array[j]) //升序 temp[k++] = array[i++]; else temp[k++] = array[j++]; } while(i <= mid) //若前一半中还有未处理完的元素 temp[k++] = array[i++]; while(j <= high) //若后一半中还有未处理完的元素 temp[k++] = array[j++]; for(i = low, j = 0; i <= high; ++i) //将排好序的元素从临时数组temp输入到array中,并释放temp; array[i] = temp[j++]; free(temp); } template <typename T> void Mergesort(T *array, int low, int high) { int mid; if(low < high) { mid = (low + high) >> 1; //递归:二分分解,直至单元素 Mergesort(array, low, mid); Mergesort(array, mid + 1, high); //合并:每次合并都是合并两个排好序的子数组 Merge(array, low, mid, high); } } //堆排序 //对堆进行调整,使下标从s到m的无序序列成为一个大顶堆 //堆的维护/保持 //一次堆维护的时间复杂度为O(lg(n)) template <typename T> void HeapAjust(T *array, int s, int m) { int j, temp = array[s]; //节点s的左子树的下标为:2s+1,右子树下标:2s+2.其实下标为0; for(j = 2*s; j <= m; j *=2) { //选出左右孩子中较大者与父节点比较 if(j < m && array[j] < array[j+1]) ++j; if(temp >= array[j]) //若父节点大于等于左右孩子,则满足大顶堆的定义,跳出循环 break; array[s] = array[j]; //否则用较大的节点替换父节点 s = j; //记录下替换父节点的节点下标 } array[s] = temp; } //堆的排序(排序过程不断的维护堆) //http://blog.csdn.net/sdlwlxf/article/details/24645557 template <typename T> void Heapsort(T *array, int len) { int i; // 建堆,堆的叶子节点下标为len/2~len-1, //初始化:第一轮循环之前:初始化时只有叶子节点,也是最大堆的根。 //保持:每次添加一个新节点都对堆进行维护保持。维护时间为O(lg(n)) //终止:当i=0时,每个都是最大堆的跟。一个堆建立了。 //建堆的时间复杂度为O(n)而不是O(nlg(n)),详见算法导论 P78. for(i = len / 2 - 1; i >= 0; --i) HeapAjust(array, i, len - 1); //每次将堆顶的元素(数组中最大的元素)与最后元素互换,最大元素就排在最后了。 //由于换过来的元素不一定满足大顶堆,需要维护一次大顶堆,再转到步骤一,直至循环结束。 //排序结束,升序。 for(i = len - 1; i > 0; --i) { swap(array[0], array[i]); HeapAjust(array, 0, i-1); } } //直接选择排序 //时间复杂度为O(n2),与序列的初始状态无关。 //不稳定:例子:2 2 1 /* 简单选择排序的基本思想:第i趟简单选择排序是指通过n-i次关键字的比较, 从n-i+1个记录中选出关键字最小的记录,并和第i个记录进行交换。共需进行i-1趟比较,直到所有记录排序完成为止。 例如:进行第i趟选择时,从当前候选记录中选出关键字最小的k号记录,并和第i个记录进行交换。 */ template <typename T> void SelectSort(T *array, int len) { int i = 0, j = 0, k = 0; for(i = 0; i < len - 1; ++i) { k = i; for(j = i+1; j < len; ++j) //从后面选择一个最小的元素 { if(array[j] < array[k]) k = j; } if(k != i) //与第i个元素交换 swap(array[i], array[k]); } } //冒泡排序,下面这并不是真正的冒泡。 template <typename T> void BubbleSort(T *array, int len) { int i = 0, j = 0; for(i = 0; i < len - 1; ++i) { for(j = i + 1; j < len; ++j) { if(array[j] < array[i]) swap(array[i], array[j]); } } } template <typename T> void BubbleSort2(T *array, int len) { int i = 0, j = 0; for(i = 0; i < len - 1; ++i) { for(j = len - 1; j > i; --j) { if(array[j] < array[j-1]) //将最小值像水中气泡冒上去。 swap(array[j], array[j-1]); } } } int main() { int num; int arr[200]; int count=0; #if 0 while(cin>>num) { arr[count++]=num; } qsort_job(arr, 0, count-1); for(int i = 0; i < count; i++) { cout << arr[i] << " "; } cout << endl; #endif while(cin>>num) { arr[count++]=num; } SelectSort(arr,count); for(int i = 0; i < count; i++) { cout << arr[i] << " "; } cout << endl; system("pause"); return 0; } /* 参考 http://blog.csdn.net/hackbuteer1/article/details/6568913 */
网络上志同道合,我们一起学习网络安全,一起进步,QQ群:694839022