一:插入排序
二:选择排序
三:交换排序
四:归并排序
五:基数排序
插入排序:(直接插入排序,shell排序)
1:直接插入排序
把左边作为已经排序好的数组,新加入的数组值和左边的数组最右边数值比较,直到不大于左边的数时停止,循环完成。最优的时间复杂度为O(n),最大时间复杂度为O(n^2),平均时间复杂度为O(n^2),是稳定的算法。
java实现代码:
package com.hdw.sort;
public class InsertSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
insertSort(a);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
}
private static void insertSort(int[] a) {
// TODO Auto-generated method stub
for(int i=1; i<a.length; i++){
int temp;
for(int j=i; j>=1; j--){
if(a[j]<a[j-1]){
temp = a[j];
a[j] = a[j-1];
a[j-1] = temp;
}else{
break;
}
}
}
}
}
2:shell排序
是对于直接插入排序的优化,shell排序中d的选取很重要,不同的时代的人对于d的选取有不同的看法,有d=2*n-1、d=3*n+1、d=5n-1,但是不管怎么选,d=1,必须要存在,这保证了排序的正确性,她的妙处在于把相邻d的数排序好,改进了对于d=1的压力,最优时间复杂度为O(n),最坏时间复杂度为O(n^2),平均时间复杂度为O(n^1.3),这个1.3是科学家算出来的,为不稳定算法。
java代码实现
package com.hdw.sort;
public class ShellSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
print(a);
shellSort(a);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
System.out.println();
}
private static void shellSort(int[] a) {
// TODO Auto-generated method stub
//第一层循环是对于d的选取
for(int d=a.length/2; d>0; d/=2){
//第二层循环是让第d个数后的每一个数和前面相差d的数做插入排序
for(int i=d; i<a.length; i++){
int temp;
//相差d的数做插入排序
for(int j=i; j>=d; j-=d){
if(a[j]<a[j-d]){
temp = a[j];
a[j] = a[j-d];
a[j-d] = temp;
}else{
break;
}
}
}
print(a);
}
}
}
选择排序:(直接选择排序,堆排序)
1:直接选择排序
把数组中最大(最小)的值,选出放在数组的开头,后面有从2到n中选出最大(最小)数放到小标为2的数中,最优,最坏,平均时间复杂度均为O(n^2),不稳定算法
java代码实现
package com.hdw.sort;
public class SelectSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
selectSort(a);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
}
private static void selectSort(int[] a) {
// TODO Auto-generated method stub
for(int i=0; i<a.length-1; i++){
int temp=a[i];
int flag = i;
for(int j=i+1; j<a.length; j++){
if(a[j]<temp){
temp = a[j];
flag = j;
}
}
a[flag] = a[i];
a[i] = temp;
}
}
}
2:堆排序
首先建立一个二叉树,把数组想象成二叉树,第一个步骤就是建立一个大顶推(小顶堆)的二叉树,第二部就是把大顶推(小顶堆)放在数组最后面一位,接下来的数再建立大顶堆(小顶堆),循环结束,最优、最差、平均时间算法O(nlog2n),不稳定算法。
java代码实现
package com.hdw.sort;
public class HeapSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
heapSort(a);
print(a);
}
private static void heapSort(int[] a) {
// TODO Auto-generated method stub
for(int i=a.length-1; i>0; i--){
createMaxHeap(a,i);
swap(a,0,i);
}
}
private static void swap(int[] a, int i, int j) {
// TODO Auto-generated method stub
a[i] = a[i] + a[j];
a[j] = a[i] - a[j];
a[i] = a[i] - a[j];
}
private static void createMaxHeap(int[] a,int lastIndex) {
// TODO Auto-generated method stub
for(int i=(lastIndex-1)/2; i>=0; i--){
int k = i;
//对K下面的树建立大顶推
while(2*k+1<=lastIndex){
//假使最大数的下标为2*k+1
int maxIndex = 2*k+1;
//如果存在右子树则比较,选择较大数的下标,为下面和父节点比较
if(maxIndex < lastIndex){
if(a[maxIndex] < a[maxIndex+1]){
maxIndex++;
}
}
//直接子节点和父节点比较,若需要交换则把k换为最大子节点的下标,好向下递推建立大顶推树,否则直接退出while循环
if(a[k] < a[maxIndex]){
swap(a, k, maxIndex);
k = maxIndex;
}else{
break;
}
}
}
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
}
}
交换排序:
1:冒泡排序
相邻两个数进行比较把大的数放在右边,循环后最大的数再数组的最右边,对剩余n-1个数使用同样的方法,最优时间复杂度O(n),最差时间复杂度O(n^2),平均时间复杂度为O(n^2),稳定算法。
java代码实现
package com.hdw.sort;
public class BubbleSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//int[] a = {9,2,7,6,4,8,1,3,5};
int[] a = {1,2,3,4,5,6};
print(a);
bubbleSort(a);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
System.out.println();
}
private static void bubbleSort(int[] a) {
// TODO Auto-generated method stub
for(int i=0; i<a.length-1; i++){
boolean flag = false;
for(int j=0; j<a.length-1-i; j++){
int temp=a[j];
if(a[j]>a[j+1]){
a[j] = a[j+1];
a[j+1] = temp;
flag = true;
}
}
if(!flag){
break;
}
print(a);
}
}
}
2:快速排序
快速排序是对于冒泡排序的改进,把中间值作为一个key,左边放的是比key小的值,右边是比key大的值,然后key左边的数进行快排,右边也进行快排,递归结束,最优时间复杂度为O(nlog2n),最差时间复杂度为O(n^2),平均时间复杂度为O(nlog2n),不稳定算法
java代码实现
package com.hdw.sort;
public class QuickSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
print(a);
quickSort(a,0,a.length-1);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
System.out.println();
}
private static void quickSort(int[] a, int left,int right){
//当可以进行快排时
if(left < right){
//把最左边的值设为key,把left的值赋给low,right的值赋给high
int key = a[left];
int low = left;
int high = right;
//当low<high时,循环把比key更大的放在它右边,比key更小的值放在它的左边
while(low<high){
//如果右边的值大于key则一直向后对比
while(low < high && a[high] >= key){
high--;
}
//符合是把高位的值赋给低位的值
a[low] = a[high];
//如果左边的值一直小于key则一直向前对比
while(low < high && a[low] < key){
low++;
}
//把地位的值赋值给高位
a[high] = a[low];
}
//把key的值赋给指针停止的地方
a[low] = key;
quickSort(a,left,low-1);
quickSort(a,low+1,right);
}
}
}
归并排序:
把数组每两个进行比较,比较完了以后作为一个整体,在两个整体之间的比较,循环下去,直到结束,我采用的是递归算法,真个数组分为两个部分,左边归并,右边也归并,最优、最差、平均时间负杂度为O(nlog2n),需要辅助空间为O(n),稳定算法
java代码实现
package com.hdw.sort;
public class MergeSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {9,2,7,6,4,8,1,3,5};
int[] temp = new int[a.length];
mergeSort(a,0,a.length-1,temp);
print(a);
}
private static void mergeSort(int[] a, int first, int last, int[] temp) {
// TODO Auto-generated method stub
if(first < last){
int mid = (first + last) / 2;
mergeSort(a,first,mid,temp);
mergeSort(a,mid+1,last,temp);
mergeArray(a,first,mid,last,temp);
}
}
private static void mergeArray(int[] a, int first, int mid, int last,
int[] temp) {
// TODO Auto-generated method stub
int i = first;
int j = mid + 1;
int m = mid;
int n = last;
int k = 0;
while(i <= m && j <= n){
if(a[i] < a[j]){
temp[k++] = a[i++];
}else{
temp[k++] = a[j++];
}
}
while(i <= m){
temp[k++] = a[i++];
}
while(j <= n){
temp[k++] = a[j++];
}
for(i = 0; i < k; i++){
a[first+i] = temp[i];
}
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
}
}
基数排序:
d为数组的最大位数,r为可区分每个数的基数的位数,比如数组里面的是整数则r=9,范围0-9,英文字母则为26,a-z,先把个位数排序,放在一个辅助的数组空间里,在把辅助空间里面值赋值给原数组,接着是百位数排序,重复,知道所有位数排序完,如果位数r比较大时,则从高位开始排序,最优时间复杂度为O(d(r+n)),最差时间复杂度为O(d(n+rd)),平均O(d(r+n)),需要辅助空间O(rd+n)
java代码实现
package com.hdw.sort;
import java.util.Arrays;
public class RadixSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {1100, 192, 221, 12, 23};
print(a);
radixSort(a,10,4);
print(a);
}
private static void print(int[] a) {
// TODO Auto-generated method stub
for (int i : a) {
System.out.print(i+",");
}
System.out.println();
}
/********************************************************
*函数名称:radixSort
*参数说明:需要排序的数组
* radix表示 基数的大小
* distance表示最高位数的大小
*说明: 通过基数排序把数组排好
*********************************************************/
private static void radixSort(int[] a, int radix, int distance) {
// TODO Auto-generated method stub
//缓存数组
int[] temp = new int[a.length];
//存储不同小标的个数
int[] count = new int[radix];
//设置每次求数组数除于的数
int rate = 1;
//把每一个位数的数比较
for(int i=0; i<distance; i++){
//把数组a的值赋值给temp数组
System.arraycopy(a, 0, temp, 0, a.length);
//初始化数组count每个值为0
Arrays.fill(count, 0);
//统计小标为key的值的个数
for(int j=0; j<a.length; j++){
int key = (temp[j]/rate)%radix;
count[key]++;
}
//对count的值进行相加,这里j是小于radix,不是a.length
for(int j=1; j<radix; j++){
count[j] += count[j-1];
}
//进行数组的交换
for(int m=a.length-1; m>=0; m--){
int subkey = (temp[m]/rate)%radix;
count[subkey]--;
a[count[subkey]] = temp[m];
}
//对下面一个位数排序
rate*=radix;
print(a);
}
}
}
![]()