9大排序知识点和源代码

常考知识点,记忆技巧:

1、平均时间:快速排序、希尔排序、归并排序和堆排序为 O(nlog2n),,其他都是n的平方。故事助记: 快(快速)些(希尔)以O(nlog2n),的速度归(归并)队(堆)

2、最坏时间:快速排序o(n的平方),其他都是和平均时间相同。

3、空间复杂度:快速排序o(log2n),归并排序o(n),基数排序 o(d),其他都是o(1).

4、算法稳定性:快速排序、希尔排序、简单选择排序、堆排序,这四种不稳定的,其他的都稳定
 一句话记忆:考研复习痛苦,心情 不稳定快(快速)些(希尔)选(选择)一堆(堆排序)好友来聊天。

5、直接插容易变成o(n),冒泡冒得好o(n), 得好,容易 插,都是指初始序列有序。

6、经过一趟排序,能够保证一个元素到达最终位置,这样的排序是交换类(快速排序,冒泡排序)和选择类(简单选择排序、堆排序)

7、排序方法的元素比较次数和原始序列无关----简单选择排序,折半插入排序。

8、排序方法的排序堂叔和原始序列有关-----交换类的排序(快速排序和冒泡排序)

9、堆排序比较适合找出前几大的数。


import java.util.HashMap;
import java.util.Random;
public class sortCategory {
public static void main(String[] args){
HashMap<Object,Object> map=new HashMap<Object,Object>();
Random random=new Random();
Object[] sorts1=new Object[100];
int[] sorts=new int[100];
System.out.println("排序前:");
int i=0;
while(map.size()<sorts1.length){
map.put(random.nextInt(1000)+1, i);
}
sorts1=map.keySet().toArray();//转换成数组
for(i=0;i<sorts1.length;i++){
sorts[i]=(int)sorts1[i];
}
for(i=0;i<sorts.length;i++){
System.out.print(sorts[i]+" ");
}
//选择排序
selectSort(sorts);
System.out.println();
System.out.println("选择算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts[i]+" ");
}
//把节点搞成完全二叉树的存储方式,从下标1开始存
int[] sorts2=new int[100];
for(i=0;i<sorts.length;i++){
sorts2[i]=(int)sorts1[i];
}
heapSort(sorts2);
System.out.println();
System.out.println("堆排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
bubbleSort(sorts2);
System.out.println();
System.out.println("冒泡排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
quickSort(sorts2,0,sorts2.length-1);
System.out.println();
System.out.println("快速排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
insertSort(sorts2);
System.out.println();
System.out.println("直接插入排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
halfInsertSort(sorts2);
System.out.println();
System.out.println("折半插入排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
shellSort(sorts2);
System.out.println();
System.out.println("希尔排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
int[] tempSort=new int[100];
mergeSort(sorts2,tempSort,0,sorts2.length-1);
System.out.println();
System.out.println("归并排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
jiShuSort(sorts2,3);
System.out.println();
System.out.println("基数排序算法排序后:");
for( i=0;i<100;i++){
System.out.print(sorts2[i]+" ");
}
}
/**
 * 选择排序
 */
/**
 * 选择排序,从头到尾顺序扫描,找出最小的一个记录,和第一个记录交换,
 * 共需选择n-1次,由于最后一次只剩一个,无需选择
 * @param R
 */
public static void selectSort(int[] R){
int temp=0;//用于交换
int min=0;//用于标志最小值的下标
for(int i=0;i<R.length-1;i++){
min=i;
for(int j=i;j<R.length;j++){
if(R[min]>R[j])
min=j; //记录最小值得下标
}
//交换两个数
temp=R[min];
R[min]=R[i];
R[i]=temp;
}
}
/**
 * 堆排序子方法
 * 1、先初始化堆,然后进行选择
 * 由于R[]组里边是一颗完全二叉树,所以元素存储必须从1开始
 */
private static void sift(int[] R,int low,int high)
{   int i=low,j=2*i+1;//i标志根节点,j表示左节点。
    int temp=R[i];//temp等于根节点;
    while(j<high){
    if(j+1<high&&R[j]<R[j+1])
    ++j;  //如果右节点比左节点大,那么j指向右结点
    if(R[j]>temp){//如果根节点比右节点小,那么交换
    R[i]=R[j];
    i=j;//右节点作为根节点
    j=2*i+1;//j等于左孩子节点
    }else
    break;
    }
    R[i]=temp;//被调整的值放到最终位置上
}
/**
 * 堆排序
 * @param R
 * @param n
 */
public static void heapSort(int[] R){
int i=0;
int temp=0; //用于交换数据
for(i=R.length/2-1;i>=0;--i) //建堆过程
sift(R,i,R.length);
for(i=R.length-1;i>=1;--i){ //对堆进行n-1趟排序
temp=R[0];
R[0]=R[i];
R[i]=temp;
sift(R,0,i-1);//对剩下的i-1个元素进行堆调整
}
}
/**
 * 冒泡排序
 */
public static void bubbleSort(int[] R){
int temp;
for(int i=0;i<R.length;i++){
for(int j=0;j<R.length-1-i;j++){
if(R[j]>R[j+1]){
temp=R[j];
R[j]=R[j+1];
R[j+1]=temp;
}
}
}
}
/**
 * 快速排序
 */
public static void quickSort(int[] R,int left,int right){
if(left<right){
int key=R[left];
int low=left,high=right;
while(low!=high){
while(low<high&&R[high]>key) high--;//如果右边的数都大于key,那么指针一直往左走
R[low]=R[high];
while(low<high&&R[left]<key) low++;//如果左边的数都小于key,那么指针一直往右走
R[high]=R[low];
}
R[low]=key;//一趟快速排序后,数组被分成两部分,此时low=high
quickSort(R,left,low-1);
quickSort(R,low+1,right);
}
}
/**
 * 直接插入排序
 */
public static void insertSort(int[] R){
int temp=0;
int j=0;
for(int i=1;i<R.length;i++){ //表示第一趟已经有序
temp=R[i];
for(j=i;j>0;j--){
if(temp<R[j-1]){
R[j]=R[j-1];
}else
break;
}
R[j]=temp;
}
}
/**
 * 折半插入排序算法
 */
public static void halfInsertSort(int[] R){
int temp=0;
int low=0,high=0,mid=0;
for(int i=1;i<R.length;i++){ //表示第一趟已经有序
temp=R[i];
low=0;
high=i-1;
while(low<=high){//通过折半循环可以找到元素要插入的位置
mid=(low+high)/2;
if(temp<R[mid])
high=mid-1;
else low=mid+1;
}
for(int j=i;j>low+1;j--)
R[j]=R[j-1];
R[low]=temp;//插入元素
}
}
/**
 * 希尔排序(Shell)算法
 */
public static void shellSort(int[] R){
int step=R.length/2; //取增量
int temp=0;//临时空间
while(step>=1){
//无须序列
for(int i=step;i<R.length;i++){
temp=R[i];//增量小区间的最后一个数
            int j=0;
for(j=i-step;j>=0;j=j-step){
   if(temp<R[j])
     R[j+step]=R[j];//排序
   else break;
}
R[j+step]=temp;
}
step=step/2;//再次取增量
}
}
/**
 * 归并排序算法
 */
public static void mergeSort(int[]R,int[] tempR,int left, int right){
if(left<right){
int middle=(left+right)/2;//取分割位置
mergeSort(R,tempR,left,middle); //递归划分数组左序列
mergeSort(R,tempR,middle+1,right);//递归划分数组右序列
merge(R,tempR,left,middle+1,right);//数组合并操作
}
}
/**
 * 
 * @param R 待排序数组
 * @param tempR 临时数组
 * @param left  第一个 区间段开始位置
 * @param middle 第二个区间的开始位置
 * @param right 第二个区间段结束的位置
 */
private static void merge(int[] R,int[] tempR,int left,int middle,int right){
int leftEnd=middle-1; //左指针尾
int rightStart=middle;//右指针
int tempIndex=left;//临时数组的小标
int tempLength=right-left+1;//数组合并后的length长度
//先循环两个区间段都没有结束的情况
while((left<=leftEnd)&&(rightStart<=right)){
if(R[left]<R[rightStart])
tempR[tempIndex++]=R[left++];
else
tempR[tempIndex++]=R[rightStart++];
}
while(left<=leftEnd)//如果还没完继续加入临时数组中
tempR[tempIndex++]=R[left++];
while(rightStart<=right)
tempR[tempIndex++]=R[rightStart++];
//交换数据
for(int i=0;i<tempLength;i++){
R[right]=tempR[right];
right--;
}
 }
/**
 * 基数排序算法
 * @param number
 * @param d
 */
public static void jiShuSort(int[]number,int d){//d表示最大的数有多少位
    int k = 0;
    int n = 1;
    int m = 1; //控制键值排序依据在哪一位
    int[][]temp = new int[10][number.length]; //数组的第一维表示可能的余数0-9
    int[]order = new int[10]; //数组orderp[i]用来表示该位是i的数的个数
    while(m <= d)
    {
        for(int i = 0; i < number.length; i++)
        {
            int lsd = ((number[i] / n) % 10);
            temp[lsd][order[lsd]] = number[i];
            order[lsd]++;
        }
        for(int i = 0; i < 10; i++)
        {
            if(order[i] != 0)
                for(int j = 0; j < order[i]; j++)
                {
                    number[k] = temp[i][j];
                    k++;
                }
            order[i] = 0;
        }
        n *= 10;
        k = 0;
        m++;
    }
}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值