排序算法汇总

此篇为main方法中调用的方式展示各排序方法的使用

package cn.first.start;

public class VarietySort {

//拓扑排序,用来确认事物发生的顺序
//选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法
//冒泡排序、插入排序、归并排序、基数排序是稳定的排序算法
public static void main(String[] arg){
	int i;
	int[] a = {10,40,30,60,80,30,20};
	//冒泡排序
	//sort(a,a.length);
	//快速排序
	sort2(a,0,a.length-1);
	//选择排序
	//sort3(a,a.length);
	//插入排序
	//sort4(a,a.length);
	//堆排序
	//sort5(a);
	//System.out.println(Arrays.toString(a));
	for(i=0;i<a.length;i++){
		System.out.println(a[i]+"\n");			
	}
	
	//希尔排序
	//VarietySort shell = new VarietySort();
	/*System.out.print("排序前:\t\t");
	shell.printAll(a);
	shell.sort6(a);
	System.out.print("排序后:\t\t");
	shell.printAll(a);*/
	
	//基数排序
    /*System.out.print("排序前:\t\t");
    shell.printAll(a);
    shell.sort7(a);
    //shell.sort(a);
    System.out.print("排序后:\t\t");
    shell.printAll(a);*/
}
/**
 * 冒泡排序
 * @param a
 * @param n
 */
public static void sort(int a[],int n){
	int i,j,num;
	int flag;
	for(i=n-1;i>0;i--){
		flag = 0;
		for(j=0;j<i;j++){
			if(a[j]>a[j+1]){
				num = a[j+1];
				a[j+1] = a[j];
				a[j] = num;
				flag=1;
			}
		}
		if(flag==0)
			break;
	}
	
}
/**
 * 快速排序,取起始位置的元素,从左往右找比起小的元素,替换。从右往左找比起大的元素,替换。循环调用
 * @param a
 * @param l
 * @param r
 */
public static void sort2(int a[],int l,int r){
	if(l<r){
		int i,j,x;
		i=l;//左第一个数
		j=r;//右第一个数
		x=a[i];
		while(i<j){
			while(i<j && a[j]>x)
				j--;//从右向左找第一个小于x的数
			if(i<j)
				a[i++]=a[j];
			while(i<j && a[i]<x)
				i++;//从左向有找第一个大于x的数
			if(i<j)
				a[j--]=a[i];
		}
		a[i]=x;
		sort2(a,l,i-1);
		sort2(a,i+1,r);
	}
}
/**
 * 选择排序,选择数组中最小的元素放在首位
 * @param a
 * @param n
 */
public static void sort3(int a[],int n){
	int i,	//无序区中末尾位置
	j,		//有序区中开始位置
	min,	//无序区中最小的元素位置
	num;
	for(i=0;i<n;i++){
		min = i;
		for(j=i+1;j<n;j++){
			if(a[j]<a[min])
				min = j;
		}
		//若min!=i,则替换a[i] 和 a[min]的位置,是a[]中的元素是有序的
		if(min!=i){
			num = a[i];
			a[i] = a[min];
			a[min] = num;
		}
	}
}
/**
 * 直接插入排序,分为有序区和无序区,从无序区中找第一个元素,放在有序区的合适的位置
 * @param a
 * @param n
 */
public static void sort4(int a[],int n){
	int i,j,k;
	for(i=1;i<n;i++){
		//为a[i]在前面的有序区内找一个合适的位置
		for(j=i-1;j>=0;j--){
			if(a[j]<=a[i])
				break;
		}
		//如找到了一个合适的位置
		if(j!=i-1){
			//将比a[i]大的数据向后移
			int temp = a[i];
			for(k=i-1;k>j;k--)
				a[k+1] =a[k];
			//将a[i]放在正确的位置上
			a[k+1] = temp;
		}
	}
}
public static int[] sort4(int[] array){
	int j;
    //从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
    for(int i = 1 ; i < array.length ; i++){
        int tmp = array[i];//记录要插入的数据
        j = i;
        while(j > 0 && tmp < array[j-1]){//从已经排序的序列最右边的开始比较,找到比其小的数
            array[j] = array[j-1];//向后挪动
            j--;
        }
        array[j] = tmp;//存在比其小的数,插入
    }
    return array;
}
/**
 * 堆排序,分为大顶堆与小顶堆,升序用大顶堆,降序用小顶堆
 * @param arr
 */
public static void sort5(int arr[]){
	//1.构建大顶堆
	for(int i=arr.length/2-1;i>=0;i--){
		//从第一个非叶子节点从下到上,从右至左调整结构
		adjustHeap(arr,i,arr.length);
	}
	//2.调整堆结构,交换堆顶结构与末尾元素
	for(int j=arr.length-1;j>0;j--){
		swap(arr,0,j);//将堆顶元素和末尾元素进行交换
		adjustHeap(arr,0,j);//重新对堆进行调整
	}
}
/**
 * 调整大顶堆,只是调整过程,建立在大顶堆已构建的基础上
 * @param arr
 * @param i
 * @param length
 */
public static void adjustHeap(int []arr,int i,int length){
	int temp = arr[i];//先取出当前元素
	for(int k=2*i+1;k<length;k=k*2+1){
		//从i节点的左子节点开始,也就是2i+1处开始
		if(k+1<length && arr[k]<arr[k+1]){
			//如果左子节点小于右子节点,取右子节点
			k++;
		}
		//如果子节点大于父节点,将子节点的值赋值给父节点(不用做交换)
		if(arr[k]>temp){
			arr[i]=arr[k];
			i=k;
		}else{
			break;
		}
	}
	arr[i]=temp;//将temp的值放到最终位置
}
public static void swap(int arr[],int a,int b){
	int temp = arr[a];
	arr[a] = arr[b];
	arr[b] = temp;
}
/**
 * 希尔排序,以数组长度的一半为一组的长度进行划分,以直接插入排序进行,再以一半的一半进行分组,循环。
 * @param list
 */
public void sort6(int[] list){
	int gap = list.length/2;
	while(1<=gap){
		//把距离为gap的元素编为一个组,扫描所有组
		for(int i=gap;i<list.length;i++){
			int j=0;
			int temp = list[i];
			
			//对距离为gap的元素进行排序
			for(j=i-gap;j>=0 && temp<list[j];j=j-gap){
				list[j+gap] = list[j];
			}
			list[j+gap] = temp;
		}
		System.out.format("gap = %d:\t",gap);
		printAll(list);
		gap = gap/2;//减少增量
	}
}
//打印完整序列
public static void printAll(int[] list){
	for(int value : list){
		System.out.print(value + "\\t");
	}
	System.out.println();
}
/**
 * 合并排序,分而治之,将整个数组等分为若干的数组,比较排序。左边取值按顺序放到右边,复制排序好的数组到之前的数组
 * @param arr
 */
public static void sort7(int []arr){
      int []temp = new int[arr.length];
      //在排序前,先建好一个长度等于原数组长度的临时数组,
      //避免递归中频繁开辟空间
      sort(arr,0,arr.length-1,temp);
  }
  private static void sort(int[] arr,int left,int right,int []temp){
      if(left<right){
          int mid = (left+right)/2;
          sort(arr,left,mid,temp);
          //左边归并排序,使得左子序列有序
          sort(arr,mid+1,right,temp);
          //右边归并排序,使得右子序列有序
          merge(arr,left,mid,right,temp);
          //将两个有序子数组合并操作
      }
  }
  private static void merge(int[] arr,int left,int mid,int right,int[] temp){
      int i = left;//左序列指针
      int j = mid+1;//右序列指针
      int t = 0;//临时数组指针
      while (i<=mid && j<=right){
          if(arr[i]<=arr[j]){
              temp[t++] = arr[i++];
          }else {
              temp[t++] = arr[j++];
          }
      }
      while(i<=mid){//将左边剩余元素填充进temp中
          temp[t++] = arr[i++];
      }
      while(j<=right){//将右序列剩余元素填充进temp中
          temp[t++] = arr[j++];
      }
      t = 0;
      //将temp中的元素全部拷贝到原数组中
      while(left <= right){
          arr[left++] = temp[t++];
      }
  }
  
  
  
  /**
   * 基数排序,按个十百千万的位数在0-9的桶中进行排序,知道最大位数排完便完成
   * @param list
   * @param begin
   * @param end
   * @param digit
   */
   public void Sort8(int[] list, int begin, int end, int digit) {
       final int radix = 10; // 基数
       int i = 0, j = 0;
       int[] count = new int[radix]; // 存放各个桶的数据统计个数
       int[] bucket = new int[end - begin + 1];
       // 按照从低位到高位的顺序执行排序过程
       for (int d = 1; d <= digit; d++) {
           // 置空各个桶的数据统计
           for (i = 0; i < radix; i++) {
               count[i] = 0;
           }
           // 统计各个桶将要装入的数据个数
           for (i = begin; i <= end; i++) {
               j = getDigit(list[i], d);
               count[j]++;
           }

           // count[i]表示第i个桶的右边界索引
           for (i = 1; i < radix; i++) {
               count[i] = count[i] + count[i - 1];
           }

           // 将数据依次装入桶中
           // 这里要从右向左扫描,保证排序稳定性
           for (i = end; i >= begin; i--) {
               j = getDigit(list[i], d); 
               // 求出关键码的第k位的数字, 例如:576的第3位是5
               bucket[count[j] - 1] = list[i]; 
               // 放入对应的桶中,count[j]-1是第j个桶的右边界索引
               count[j]--; // 对应桶的装入数据索引减一
           }
           // 将已分配好的桶中数据再倒出来,此时已是对应当前位数有序的表
           for (i = begin, j = 0; i <= end; i++, j++) {
               list[i] = bucket[j];
           }
       }
   }
   // 获取x这个数的d位数上的数字
   // 比如获取123的1位数,结果返回3
   public int getDigit(int x, int d) {
       int a[] = {
               1, 1, 10, 100
       }; // 本实例中的最大数是百位数,所以只要到100就可以了
       return ((x / a[d]) % 10);
   }
   public int[] sort(int[] list) {
       Sort8(list, 0, list.length - 1, 3);
       return list;
   }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值