算法学习笔记——排序问题
2016-11-14 16:28
246 查看
学习笔记,仅做记录,如有错漏,望指出,谢谢。
平均时间复杂度为:O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),稳定(排序算法稳定性详见百度百科)
空间复杂度为O(1)
∑i=0n−2∑j=i+1n−1=∑i=0n−2(n−i−1)=n(n−1)2=O(n2)
平均时间复杂度为:O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),空间复杂度为O(1),稳定
首先将元素分为有序区和无序区,初始时,有序区为零。遍历比较无序区中的相邻元素,将较大元素后移,并记录每次最后发生交换的位置,以确定有序区和无序区。重复遍历比较无序区中相邻元素直至无序区为零。
平均时间复杂度为O(nlog2n)最坏时间复杂度为O(n2),最好时间复杂度为O(nlog2n),空间复杂度为O(nlog2n),不稳定
对待排序元素进行扫描,确定中间的轴值,以轴值为划分,一侧元素均小于轴值,一侧元素均大于轴值。对以轴值划分的区域递归排序。
时间复杂度为O(nlog2n)(执行一次合并算法的时间复杂度为O(n)),空间复杂度为O(n),稳定
对待排序序列进行划分,直至序列有序(即序列长度为1),对有序子序列进行合并,直至排序完成
平均时间复杂度为O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),空间复杂度为O(1),稳定
将待排序序列划分为有序区和无序区,初始有序区元素个数为零,取无序区第一个元素,与有序区元素逐个毕竟,插入到合适位置,直至无序区元素个数为零
堆(heap)是具有下列性质的完全二叉树:每个结点的值都小于(大于)或等于其左右孩子结点的值
时间复杂度为O(nlog2n),空间复杂度为O(1),不稳定
1.简单选择排序(选择类排序)
使用方法:蛮力法平均时间复杂度为:O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),稳定(排序算法稳定性详见百度百科)
空间复杂度为O(1)
∑i=0n−2∑j=i+1n−1=∑i=0n−2(n−i−1)=n(n−1)2=O(n2)
package com.viper.sort; public class SelectSort { public static void sort(int array[]) { for (int i = 0; i < array.length; i++) { int index = i; for (int j = i + 1; j < array.length; j++) { // 查找无序区最小的记录 if (array[j] < array[index]) index = j; } if (index != i) { // 将无序区最小的记录添加到有序区末尾 int temp = array[i]; array[i] = array[index]; array[index] = temp; } } } }
2.冒泡排序(交换类排序)
使用方法:蛮力法平均时间复杂度为:O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),空间复杂度为O(1),稳定
首先将元素分为有序区和无序区,初始时,有序区为零。遍历比较无序区中的相邻元素,将较大元素后移,并记录每次最后发生交换的位置,以确定有序区和无序区。重复遍历比较无序区中相邻元素直至无序区为零。
package com.viper.sort; public class BubbleSort { public static void sort(int[] array) { int bound, exchange = array.length - 1; while (exchange != 0) { bound = exchange; exchange = 0;//重置为零,若未交换则排序完毕 for (int i = 0; i < bound; i++) { if (array[i] > array[i + 1]) { int temp = array[i]; array[i] = array[i + 1]; array[i + 1] = temp; exchange = i;//记录每次交换的位置 } } } } }
3.快速排序(交换类排序)
使用方法:分治法平均时间复杂度为O(nlog2n)最坏时间复杂度为O(n2),最好时间复杂度为O(nlog2n),空间复杂度为O(nlog2n),不稳定
对待排序元素进行扫描,确定中间的轴值,以轴值为划分,一侧元素均小于轴值,一侧元素均大于轴值。对以轴值划分的区域递归排序。
package com.viper.sort; public class QuickSort { public static void sort(int[] array) { quickSort(array, 0, array.length - 1); } /** * 快速排序 */ private static void quickSort(int[] array, int first, int end) { int pivot; if (first < end) { pivot = partition(array, first, end); quickSort(array, first, pivot - 1); quickSort(array, pivot + 1, end); } } /** * 扫描并划分待排序元素,返回轴值 */ private static int partition(int array[], int first, int end) { int i = first, j = end; while (i < j) {// i==j停止,确定轴值 while (i < j && array[i] <= array[j]) { j--; } if (i < j) { swap(array[i], array[j]); i++; } while (i < j && array[i] <= array[j]) { i++; } if (i < j) { swap(array[i], array[j]); j--; } } return i; } private static void swap(int a, int b) { int temp = a; a = b; b = temp; } }
5.归并排序
使用方法:分治法时间复杂度为O(nlog2n)(执行一次合并算法的时间复杂度为O(n)),空间复杂度为O(n),稳定
对待排序序列进行划分,直至序列有序(即序列长度为1),对有序子序列进行合并,直至排序完成
package com.viper.sort; public class MergeSort { public static void sort(int[] array) { mergeSort(array, 0, array.length - 1); } private static void mergeSort(int[] array, int start, int end) { if (start == end) { return; } else { int mid = (start + end) / 2; //递归划分 mergeSort(array, start, mid); mergeSort(array, mid + 1, end); //合并子序列 merge(array, start, mid, end); } } private static void merge(int[] array, int start, int mid, int end) { int[] tempArr = new int[array.length]; int i = start, j = mid + 1, k = start; while (i < mid && j < end) { if (array[i] <= array[j]) { tempArr[k++] = array[i++]; } else { tempArr[k++] = array[j++]; } } //将未处理完的序列依次放入结果中 while (i <= mid) { tempArr[k++] = array[i++]; } while (j <= end) { tempArr[k++] = array[j++]; } //将已排序序列复制回原序列 while(start <= k) { array[k] = tempArr[k--]; } } }
4.直接插入排序(插入类排序)
使用方法:减治法平均时间复杂度为O(n2),最坏时间复杂度为O(n2),最好时间复杂度为O(n),空间复杂度为O(1),稳定
将待排序序列划分为有序区和无序区,初始有序区元素个数为零,取无序区第一个元素,与有序区元素逐个毕竟,插入到合适位置,直至无序区元素个数为零
package com.viper.sort; public class InsertSort { public static void sort(int[] array) { for (int i = 1; i < array.length; i++) { int j, temp = array[i]; for (j = i - 1; j > 0 && temp < array[j]; j--) { array[j + 1] = array[j]; } array[j + 1] = temp; } } }
6.堆排序(选择类排序)
使用方法:减治法堆(heap)是具有下列性质的完全二叉树:每个结点的值都小于(大于)或等于其左右孩子结点的值
时间复杂度为O(nlog2n),空间复杂度为O(1),不稳定
package com.viper.sort; public class HeapSort { public static void sort(int[] array) { int i, temp; for (i = array.length - 1; i >= 0; i--) { siftHeap(array, i, array.length);// 初始建堆,从最后一个分支开始 } for (i = 1; i < array.length; i++) { temp = array[0]; array[0] = array[array.length - i]; array[array.length - i] = temp; siftHeap(array, 0, array.length - i);//调整当前根结点 } } /** * 筛选法调整堆 */ private static void siftHeap(int[] array, int k, int n) { int i = k, j = 2 * i + 1, temp;// i根结点,j指向左孩子 while (j < n) {// 判断是否为叶子结点 if (j < n - 1 && array[j] < array[j + 1]) { j++; } if (array[i] > array[j]) {// 根结点值较大 break; } else {// 交换根结点与较大孩子结点 temp = array[i]; array[i] = array[j]; array[j] = temp; } } } }
7.希尔排序(插入类排序)
平均时间复杂度为O(nlog2n),最坏时间复杂度为O(nlog2n),空间复杂度为O(1),希尔排序不稳定package com.viper.sort; public class ShellSort { public static void sort(int[] array) { for (int step = 5;step > 0; step--) {//此处step默认为5 for (int i = 0; i < step; i++) {// 每一组 for (int j = i + step; j < array.length; j += step) {// 插入排序 int k, temp = array[j]; for (k = j - step; k >= 0 && temp < array[k]; k -= step) { array[k + step] = array[k]; } array[j + step] = temp; } } } } }
8.基数排序
相关文章推荐
- 【算法学习笔记】51. 贪心法 区间排序问题 SJTU OJ 1360 偶像丁姐的烦恼
- 算法学习笔记之排序--基于指针的插入排序
- 算法学习笔记之排序--基于值的插入排序
- 算法设计和数据结构学习_4(《数据结构和问题求解》part4笔记)
- 算法学习笔记之四:巧妙运用指针解决链表、字符串、数组等问题(同向双指针VS对向双指针)
- 算法学习笔记——利用栈解决实际问题- part 2
- 算法学习笔记之排序--基于值的插入排序
- 算法学习笔记----最长公共子序列问题
- 精确覆盖问题学习笔记(三)——算法的初步实现
- 算法学习笔记----第二部分:排序和顺序统计量----第6章、堆排序
- Java 线程同步问题 生产者-消费者 算法实现 -Java学习笔记(29)
- 数据结构学习笔记一:简单排序与查询算法
- 韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
- 精确覆盖问题学习笔记(五)——优化算法的实现代码
- 烙饼排序问题最优次数求解 暑期学习笔记(九)
- python学习笔记:二维数组排序问题
- 算法学习笔记----归并排序
- 算法学习笔记----最大子数组问题
- 黑马程序员—Java基础学习笔记之排序算法:选择排序&冒泡排序
- 算法学习笔记之插入排序