网站维护多少钱一个月,黄山网站建设电话,开封府景点网站建设的目的,用dw做网站时怎么添加弹窗排序算法 1. 排序的概念及引用1.1 排序的概念1.2 常见的排序算法 2. 常见排序算法的实现2.1 插入排序2.1.1 直接插入排序2.1.2 希尔排序( 缩小增量排序 ) 2.2 选择排序2.2.1 直接选择排序2.2.2 堆排序 2.3 交换排序2.3.1冒泡排序2.3.2 快速排序2.3.3 快速排序非递归 2.4 归并排… 排序算法 1. 排序的概念及引用1.1 排序的概念1.2 常见的排序算法 2. 常见排序算法的实现2.1 插入排序2.1.1 直接插入排序2.1.2 希尔排序( 缩小增量排序 ) 2.2 选择排序2.2.1 直接选择排序2.2.2 堆排序 2.3 交换排序2.3.1冒泡排序2.3.2 快速排序2.3.3 快速排序非递归 2.4 归并排序 3. 排序算法复杂度及稳定性分析 1. 排序的概念及引用
1.1 排序的概念
排序所谓排序就是使一串记录按照其中的某个或某些关键字的大小递增或递减的排列起来的操作。
稳定性假定在待排序的记录序列中存在多个具有相同的关键字的记录若经过排序这些记录的相对次序保持不变即在原序列中r[i]r[j]且r[i]在r[j]之前而在排序后的序列中r[i]仍在r[j]之前则称这种排序算法是稳定的否则称为不稳定的。
内部排序数据元素全部放在内存中的排序
外部排序数据元素太多不能同时放在内存中根据排序过程的要求不能在内外存之间移动数据的排序。
1.2 常见的排序算法 2. 常见排序算法的实现
2.1 插入排序
基本思想
直接插入排序是一种简单的插入排序法其基本思想是
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中直到所有的记录插入完为止得到一个新的有序序列 。实际中我们玩扑克牌时就用了插入排序的思想。
2.1.1 直接插入排序
当插入第i(i1)个元素时前面的array[0],array[1],…,array[i-1]已经排好序此时用array[i]的排序码与array[i- 1],array[i-2],…的排序码顺序进行比较找到插入位置即将array[i]插入原来位置上的元素顺序后移
直接插入排序的特性总结 1. 元素集合越接近有序直接插入排序算法的时间效率越高 2. 时间复杂度O(N^2) 3. 空间复杂度O(1)它是一种稳定的排序算法 4. 稳定性稳定
public static void insertSort(int[] array) {for (int i 1; i array.length; i) {int tmp array[i];int j i-1;for (; j 0 ; j--) {//这里加不加等号 和稳定有关系// 但是本身就是一个稳定的排序 可以实现为不稳定的排序// 但是 本身就是一个不稳定的排序 是不可能变成一个稳定的排序的if(array[j] tmp) {array[j1] array[j];}else {//array[j1] tmp;break;}}array[j1] tmp;}}2.1.2 希尔排序( 缩小增量排序 )
希尔排序法又称缩小增量法。希尔排序法的基本思想是先选定一个整数把待排序文件中所有记录分成多个组所有距离为的记录分在同一组内并对每一组内的记录进行排序。然后取重复上述分组和排序的工作。当到达1时所有记录在统一组内排好序。 希尔排序的特性总结
希尔排序是对直接插入排序的优化。当gap 1时都是预排序目的是让数组更接近于有序。当gap 1时数组已经接近有序的了这样就会很 快。这样整体而言可以达到优化的效果。我们实现后可以进行性能测试的对比。希尔排序的时间复杂度不好计算因为gap的取值方法很多导致很难去计算因此在好些书中给出的希尔排 序的时间复杂度都不固定稳定性不稳定 //希尔排序public static void shellSort(int[] array) {int gap array.length;while (gap 1) {gap / 2;shell(array,gap);}}/*** 对每组进行插入排序* param array* param gap*/public static void shell(int[] array,int gap) {for (int i gap; i array.length; i) {int tmp array[i];int j i-gap;for (; j 0 ; j-gap) {//这里加不加等号 和稳定有关系// 但是本身就是一个稳定的排序 可以实现为不稳定的排序// 但是 本身就是一个不稳定的排序 是不可能变成一个稳定的排序的if(array[j] tmp) {array[jgap] array[j];}else {//array[j1] tmp;break;}}array[jgap] tmp;}}2.2 选择排序
基本思想
每一次从待排序的数据元素中选出最小或最大的一个元素存放在序列的起始位置直到全部待排序的数据元素排完 。
2.2.1 直接选择排序
在元素集合array[i]–array[n-1]中选择关键码最大(小)的数据元素若它不是这组元素中的最后一个(第一个)元素则将它与这组元素中的最后一个第一个元素交换在剩余的array[i]–array[n-2]array[i1]–array[n-1]集合中重复上述步骤直到集合剩余1个元素
【直接选择排序的特性总结】
直接选择排序思考非常好理解但是效率不是很好。实际中很少使用时间复杂度O(N^2)空间复杂度O(1)稳定性不稳定
/*** 选择排序* 时间复杂度O(n^2)* 空间复杂度O(1)* 稳定性不稳定的排序* param array*/public static void selectSort(int[] array) {for (int i 0; i array.length; i) {int minIndex i;for (int j i1; j array.length; j) {if(array[j] array[minIndex]) {minIndex j;}}swap(array,i,minIndex);}}2.2.2 堆排序
堆排序(Heapsort)是指利用堆积树堆这种数据结构所设计的一种排序算法它是选择排序的一种。它是通过堆 来进行选择数据。需要注意的是排升序要建大堆排降序建小堆。
private static void createHeap(int[] array) {for (int parent (array.length-1-1)/2; parent 0 ; parent--) {siftDown(array,parent,array.length);//altenter}}private static void siftDown(int[] array,int parent, int length) {int child 2*parent 1;while (child length) {if(child1 length array[child] array[child1]) {child;}if(array[child] array[parent]) {swap(array,child,parent);parent child;child 2*parent1;}else {break;}}}/*** 时间复杂度O(N*logN)* 空间复杂度O(1)* 稳定性不稳定的排序* param array*/public static void heapSort(int[] array) {createHeap(array);int end array.length-1;while (end 0) {swap(array,0,end);siftDown(array,0,end);end--;}}
2.3 交换排序
基本思想所谓交换就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置交换排序的特点是将键值较大的记录向序列的尾部移动键值较小的记录向序列的前部移动。
2.3.1冒泡排序
【冒泡排序的特性总结】
冒泡排序是一种非常容易理解的排序时间复杂度O(N^2)空间复杂度O(1)稳定性稳定
/*** 时间复杂度O(N^2)* 如果加了优化最好情况下 可以达到O(n)* 空间复杂度O(1)* 稳定性稳定的排序** 优化* 每一趟都需要判断 上一趟 有没有交换* param array*/public static void bubbleSort(int[] array) {//i代表的是趟数for (int i 0; i array.length-1; i) {boolean flg false;//j来比较 每个数据的大小for (int j 0; j array.length-1-i; j) {if(array[j] array[j1]) {swap(array,j,j1);flg true;}}if(!flg) {break;}}}2.3.2 快速排序
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法其基本思想为任取待排序元素序列中的某元素作为基准值按照该排序码将待排序集合分割成两子序列左子序列中所有元素均小于基准值右子序列中所有元素均大于基准值然后最左右子序列重复该过程直到所有元素都排列在相应位置上为止
void QuickSort(int[] array, int left, int right){if(right - left 1)return;// 按照基准值对array数组的 [left, right)区间中的元素进行划分int div partion(array, left, right);// 划分成功后以div为边界形成了左右两部分 [left, div) 和 [div1, right)// 递归排[left, div)QuickSort(array, left, div-1);// 递归排[div1, right)QuickSort(array, div1, right);}上述为快速排序递归实现的主框架发现与二叉树前序遍历规则非常像同学们在写递归框架时可想想二叉树前序遍历规则即可快速写出来后序只需分析如何按照基准值来对区间中数据进行划分的方式即可。 将区间按照基准值划分为左右两半部分的常见方式有
Hoare版
private static int partition(int[] array, int left, int right) {int i left;int j right;int pivot array[left];while (i j) {while (i j array[j] pivot) {j--;}while (i j array[i] pivot) {i;}swap(array, i, j);}swap(array, i, left);return i;
}挖坑法
private static int partition(int[] array, int left, int right) {int i left;int j right;int pivot array[left];while (i j) {while (i j array[j] pivot) {j--;}array[i] array[j];while (i j array[i] pivot) {i;}array[j] array[i];}array[i] pivot;return i;}前后指针
private static int partition(int[] array, int left, int right) {int prev left ;int cur left1;while (cur right) {if(array[cur] array[left] array[prev] ! array[cur]) {swap(array,cur,prev);}cur;}swap(array,prev,left);return prev;}2.3.3 快速排序非递归
void quickSortNonR(int[] a, int left, int right) {StackInteger st new Stack();st.push(left);st.push(right);while (!st.empty()) {right st.pop();left st.pop();if(right - left 1)continue;int div PartSort1(a, left, right);// 以基准值为分割点形成左右两部分[left, div) 和 [div1, right)st.push(div1);st.push(right);st.push(left);st.push(div);}}快速排序总结
快速排序整体的综合性能和使用场景都是比较好的所以才敢叫快速排序时间复杂度O(N*logN)空间复杂度O(logN)稳定性不稳定
2.4 归并排序
基本思想
归并排序MERGE-SORT是建立在归并操作上的一种有效的排序算法,该算法是采用分治法Divide and Conquer的一个非常典型的应用。将已有序的子序列合并得到完全有序的序列即先使每个子序列有序再使子序列段间有序。若将两个有序表合并成一个有序表称为二路归并。 归并排序核心步骤 /*** 时间复杂度O(N*logN)* 空间复杂度O(logN)* 稳定性稳定的排序* 目前为止3个稳定的排序直接插入排序、冒泡排序、归并排序* param array*/public static void mergeSort(int[] array) {mergeSortFun(array,0,array.length-1);}private static void mergeSortFun(int[] array,int start,int end) {if(start end) {return;}int mid (startend)/2;mergeSortFun(array,start,mid);mergeSortFun(array,mid1,end);//合并merge(array,start,mid,end);}private static void merge(int[] array, int left, int mid, int right) {int s1 left;//可以不定义这样写为了好理解int e1 mid;//可以不定义这样写为了好理解int s2 mid1;int e2 right;//可以不定义这样写为了好理解//定义一个新的数组int[] tmpArr new int[right-left1];int k 0;//tmpArr数组的下标//同时满足 证明两个归并段 都有数据while (s1 e1 s2 e2) {if(array[s1] array[s2]) {tmpArr[k] array[s1];}else {tmpArr[k] array[s2];}}while (s1 e1) {tmpArr[k] array[s1];}while (s2 e2) {tmpArr[k] array[s2];}//把排好序的数据 拷贝回原来的数组array当中for (int i 0; i tmpArr.length; i) {array[ileft] tmpArr[i];}}
归并排序总结
归并的缺点在于需要O(N)的空间复杂度归并排序的思考更多的是解决在磁盘中的外排序问题。时间复杂度O(N*logN)空间复杂度O(N)稳定性稳定
【 海量数据的排序问题】
外部排序排序过程需要在磁盘等外部存储进行的排序
前提内存只有 1G需要排序的数据有 100G
因为内存中因为无法把所有数据全部放下所以需要外部排序而归并排序是最常用的外部排序
先把文件切分成 200 份每个 512 M分别对 512 M 排序因为内存已经可以放的下所以任意排序方式都可以进行 2路归并同时对 200 份有序文件做归并过程最终结果就有序了
3. 排序算法复杂度及稳定性分析