快速排序:
/*
* 快速排序:选取flag(这里选第一个数),先从右边开始找到小于它的数,交换,再从左边开始找到大于它的数,交换,
* 这样它就在合适的位置,并把数组分为两个部分,分别重复上述步骤即可。
* 时间复杂度:O(nlogn)
* 稳定性:不稳定
*/
public class QuickSort {
public static void quickSort(int[] a, int left, int right){
if(left < right){
int flag = a[left];
int i = left;
int j = right;
while(true){
while(a[j] >= flag && j > i){
j--;
}
if(a[j] < flag){
int tmp = a[j];
a[j] = a[left];
a[left] = tmp;
}
while(a[i] <= flag && i<j){
i++;
}
if(a[i] > flag){
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
if(i >= j){
break;
}
}
quickSort(a, left, i);
quickSort(a, i+1, right);
}
}
public static void main(String[] args){
int[] a = {21,5,23,1,8};
quickSort(a, 0, a.length-1);
for(int x:a){
System.out.print(x + " ");
}
}
}
归并排序:
/*
* 归并排序:利用分治思想,将序列每次折半划分,将划分的序列排序合并
* http://www.cnblogs.com/jingmoxukong/p/4308823.html
* 时间复杂度:O(nlogn)
* 稳定性:稳定
*/
public class MergeSort {
public static void mergesort(int[] a, int[] tmp, int left, int right){
if(left < right){
int mid = (right + left) / 2;
mergesort(a, tmp, left, mid); //左边部分
mergesort(a, tmp, mid+1, right); //右边部分
sort(a,tmp,left,mid+1,right); //归并
}
}
public static void sort(int[] a, int[] tmp, int left, int mark, int right){
int leftend = mark - 1; //左边的极限
int numElement = right - left + 1; //数量
int len = left; //tmp数组长度
while(left <= leftend && mark <= right){
if(a[left] < a[mark]){
tmp[len++] = a[left++];
}else{
tmp[len++] = a[mark++];
}
}
while(left <= leftend){
tmp[len++] = a[left++];
}
while(mark <= right){
tmp[len++] = a[mark++];
}
for(int i=0; i<numElement; i++,right--){
a[right] = tmp[right];
}
}
public static void main(String[] args){
int[] a = {21,5,23,1,8};
int[] tmp = new int[a.length];
mergesort(a,tmp, 0, a.length-1);
for(int x:a){
System.out.print(x + " ");
}
}
}
堆排序:
/*
* 1. 构建一个最大堆。对于给定的包含有n个元素的数组A[n],构建一个最大堆从最底下的子树开始,
* 调整这个堆结构,使其满足最大堆的特性。当为了满足最大堆特性时,堆结构发生变化,此时递归调整对应的子树。
* 2. 堆排序算法,每次取出该最大堆的根节点(因为根节点是最大的),同时,取最末尾的叶子节点来作为根节点,
* 从此根节点开始调整堆,使其满足最大堆的特性。
* 3. 重复上一步操作,直到堆的大小由n个元素降到2个。
* 详解:http://dsbryz.iteye.com/blog/1182056
* 时间复杂度:O(nlogn)
* 稳定性:不稳定
*/
public class HeapSort {
public static void heapSort(int[] a){
buildHeapfirst(a); //第一次构造大根堆
int len = a.length;
for(int i = len; i>1; i--){ //将最大值赋给 a[0]
int tmp = a[0];
a[0] = a[i-1];
a[i-1] = tmp;
buildHeapnext(a, 1, i-1); //i为数组大小-1
}
}
//从最底下的子树构造大根堆
public static void buildHeapfirst(int[] a){
for(int i=a.length / 2; i>0; i--){
buildHeapnext(a, i, a.length);
}
}
//堆调整,使其生成最大堆
public static void buildHeapnext(int[] a, int parentIndex, int heapSize){
int left = parentIndex * 2; //左儿子,对应数组中为:a[left-1]:(partIndex)*2-1
int right = parentIndex * 2 + 1;
int largestIndex = parentIndex; //最大值:初始而父节点
// 如果左子节点大于父节点,则将左子节点作为最大节点
if(left <= heapSize && a[left-1] > a[parentIndex-1]){
largestIndex = left;
}
// 如果右子节点比最大节点还大,那么最大节点应该是右子节点
if(right <= heapSize && a[right-1] > a[largestIndex-1]){
largestIndex = right;
}
// 最后,如果最大节点和父节点不一致,则交换他们的值
if(largestIndex != parentIndex){
int tmp = a[parentIndex-1];
a[parentIndex-1] = a[largestIndex-1];
a[largestIndex-1] = tmp;
// 交换完父节点和子节点的值,对换了值的子节点检查是否符合最大堆的特性
buildHeapnext(a, largestIndex, heapSize);
}
}
public static void main(String[] args){
int[] a = {21,1,5,7,7,5,23,2,1,8};
heapSort(a);
for(int x:a){
System.out.print(x + " ");
}
}
}
选择排序:
/*
* 选择排序:对应的位置选择对应的值,这里从前往后一次增大。
* 时间复杂度:O(n^2)
* 稳定性:不稳定
*/
public class SelectSort {
public static void selectSort(int[] a){
int len = a.length;
for(int i=0; i<len; i++){
for(int j=i+1; j<len; j++){
if(a[j] < a[i]){
int tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
}
}
}
public static void main(String[] args){
int[] a = {21,5,23,1,8};
selectSort(a);
for(int x:a){
System.out.print(x + " ");
}
}
}
插入排序:
/*
* 插入排序:从第二个数开始,前面的数都是排好序的,那么新插入的数只要交换到合适的位置就是排好序的。
* 时间复杂度:O(n^2)
* 稳定性:稳定
*/
public class InsertSort {
public static void insertSort(int[] a){
int len = a.length;
if(len == 1){
return;
}
int target;
for(int i=1; i<len; i++){ //从第二个数开始排序
target = a[i];
int j = i;
while(j > 0 && target < a[j-1]){ //找到target合适的位置,并交换
a[j] = a[j-1]; //将前面的数赋给后面的
j--;
}
if(j != i){
a[j] = target; //如果发生过交换则将target赋给最前面的数
}
}
}
public static void main(String[] args){
int[] a = {21,5,23,1,8};
insertSort(a);
for(int x:a){
System.out.print(x + " ");
}
}
}
计数排序:
/*
* 桶排序:用一个理想的大数组保存出现的每一个值次数,即a[i]为i出现的次数,i为这个数。
* 时间复杂度:O(N+C),其中C=N*(logN-logM),N个待排数据,M个桶,
* 稳定性:稳定
*/
public class BucketSort {
public static void bucketSort(int[] a, int maxlen){
int[] max = new int[maxlen]; //桶(数组)
for(int i=0; i<a.length; i++){
max[a[i]]++; //对应桶中数的数量加一
}
for(int i=0,j=0; i<maxlen; i++){
if(max[i] != 0){
while(max[i] > 0){
a[j++] = i;
max[i]--;
}
}
}
}
public static void main(String[] args){
int[] a = {21,1,5,7,7,5,23,1,8};
int maxlen = 100;
bucketSort(a,maxlen);
for(int x:a){
System.out.print(x + " ");
}
}
}
基数排序:
/*
* 初始化: 构造一个10*n的二维数组,一个长度为n的数组用于存储每次位排序时每个桶子里有多少个元素。
* 循环操作:从低位开始(我们采用LSD的方式),将所有元素对应该位的数字存到相应的桶子里去(对应二维数组的那一列)。
* 然后将所有桶子里的元素按照桶子标号从小到大取出,对于同一个桶子里的元素,先放进去的先取出,后放进去的后取出(保证排序稳定性)。
* 这样原数组就按该位排序完毕了,继续下一位操作,直到最高位排序完成。
* 详解:http://www.cnblogs.com/developerY/p/3172379.html
* 时间复杂度:Θ(d*n),循环d次
* 稳定性:稳定
*/
public class RedixSort {
public static void redixSort(int[] a, int maxlen){
System.out.println(maxlen);
int len = a.length;
int[][] bucket = new int[10][len]; //桶数组,保存实际的值
int[] numOfbucket = new int[len]; //保存对应桶数组中元素的个数
int n = 1; //个位、十位、百位
while(n < maxlen){
for(int x: a){
int digit = (x / n) % 10;
bucket[digit][numOfbucket[digit]] = x;
numOfbucket[digit]++; //digit对应数组中元素个数加一
}
int k = 0;
for(int i=0; i<len; i++){ //遍历numOfbucket数组
if(numOfbucket[i] != 0){
for(int j=0; j < numOfbucket[i]; j++){
a[k] = bucket[i][j];
k++;
}
}
numOfbucket[i] = 0; //将桶里计数器置0,用于下一次位排序
}
n *= 10;
}
}
public static void main(String[] args){
int[] a = {21,1,5,7,700,5,23,1,8};
int max = 0; //最大数
for(int i=0; i<a.length; i++){
if(a[i] > max){
max = a[i];
}
}
int maxlen = 0; //最大数的位数+1
while(max > 0){
max /= 10;
maxlen++;
}
redixSort(a,(int)Math.pow(10, maxlen));
for(int x:a){
System.out.print(x + " ");
}
}
}
希尔排序:
/*
* 希尔排序也成为“缩小增量排序”,其基本原理是,现将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,
* 然后对各个子序列分别进行直接插入排序,待整个待排序列“基本有序”后,最后在对所有元素进行一次直接插入排序 。
* 时间复杂度:O(nlogn)
* 稳定性:不稳定
*/
public class HillSort {
public static void hillSort(int[] a){
int len = a.length;
for(int increment=len/2; increment>0; increment /= 2){ //初始增量为len/2,逐渐缩小增量
for(int i=increment; i<len; i++){
int flag = a[i];
int j;
for(j = i-increment; j>=0; j -= increment){
if(flag < a[j]){ //后面的数比前面的小
a[j+increment] = a[j]; //将前面的数赋值给后面的
}else{
break;
}
}
a[j+increment] = flag; //将后面的赋值给前面的
}
}
}
public static void main(String[] args){
int[] a = {21,5,23,1,8};
hillSort(a);
for(int x:a){
System.out.print(x + " ");
}
}
}
冒泡排序:
/*
* 冒泡排序:相邻数进行比较,将大的数沉入数组低端,小的数“冒”到顶端。
* 时间复杂度为:O(n^2)
* 稳定性:稳定
*/
public class BubbleSort {
public static void bubbleSort(int[] a){
int len = a.length;
for(int i=0; i<len-1; i++){
for(int j=0; j<len-1-i; j++){ //每趟排序结束后数组最后都是最大的值,不用排序,所以j的最大值是len-1-i
if(a[j] > a[j+1]){
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
}
}
public static void main(String[] args){
int[] a = {21,5,23,1,8};
bubbleSort(a);
for(int x:a){
System.out.print(x + " ");
}
}
}