数据结构——七大排序

排序算法的分类:

排序:基本排序:{交换排序:冒泡排序,快速排序。(快速排序相当于冒泡排序的升级)

                             {选择排序:选择排序,堆排序(堆排序相当于选择排序的升级)

                             {插入排序:直接插入排序,Shell排序(希尔排序相当于直接插入排序的升级)

                             {归并排序

           多路归并排序:

一:交换排序

1:交换排序的主体操作是对数组中的数据不断进行交换操作。

2:交换排序种类:交换排序主要有冒泡排序和快速排序。

1:冒泡排序

(1)冒泡排序流程

——(1)对数组中的各元素,一次比较相邻的两个元素的大小

——(2)如果前面的数据大于后面的数据,就交换着两个数据。经过第一轮的多次比较排序之后,便可将最小的数据排好

——(3)在用同样的方法把剩下的数据逐个进行比较,最后便可按照从小到大的顺序排好数组个数据的顺序。

(2)冒泡代码分析

优点:思路简单直观。

缺点:执行的步骤有点长,效率不是很高。

时间效率:没有数据交换时间复杂度O(n),最坏的情况为数组逆序,时间复杂度为O(n^2)

空间效率:仅使用了一个辅存单元。

(3)冒泡排序代码

public void bubblesort(){
    int[] data={10,9,8,7,6,5,4};
    System.out.println("排序之前");
    System.out.println(java.util.Arrays.toString(data));
    int n=data.length;
    for(int i=0;i<n-1;i++){
       for(int j=0;j<n-1-i;j++){
           if(data[j]-data[j+1]>0){
               int temp=data[j];
               data[j]=data[j+1];
               data[j+1]=temp;
           }
       }
    }
    System.out.println("排序之后:\n");
    System.out.println(java.util.Arrays.toString(data));
}

2:快速排序

(1)快速排序流程

——(1)首先设定一个分界值,通过该分界值将数据分成左右两个部分。

——(2)将大于等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。

此时,左边部分中的各元素都小于等于分界值,而右边部分中各元素都大于等于分界值。

——(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,

同样将左边放置较小值,右边放置较大值。右边的数据也做这样的处理。

——(4)重复上述过程。

(2)快速排序代码分析

快速排序,平均O(nlogn),最坏O(n^2),空间O(logn),不稳定

时间效率:待排序序列本身已经有序或逆向有序时,快速排序的时间复杂度为Ο(n 2 ),

而在有序时插入排序的时间复杂度为Ο(n)。

空间效率:

(3)快速排序代码

public class AMoNiStack {
    public static void main(String[] args){
        AMoNiStack a=new AMoNiStack();
        int[] b={1,4,5,32,7,54,2};
        a.quicksort(b,0,b.length-1);
        for(int i:b){
            System.out.print(" "+i);
        }
    }
    public void  quicksort(int a[],int start,int end){
        int i=start;
        int j=end;
        boolean flag=true;
        if(i>=j){
            return ;
        }
        while(i!=j){
            if(a[i]>a[j]){
                int temp=a[i];
                a[i]=a[j];
                a[j]=temp;
                flag=!flag;
            }
            if(flag){
                j--;
            }else{
                i++;
            }
        }
        i--;
        j++;
        quicksort(a,start,i);
        quicksort(a,j,end);
    }

}

 

二:选择排序

1:简单选择排序

(1)选择排序流程

——(1)首先从原始数组中选择最小的1个数据,将其和第一个位置的数据交换。

——(2)接着从剩下的n-1个数据中选择次小的一个元素,将其和第二个位置的数据对换。

——(3)然后这样不断重复,直到最后两个数据完成对换。至此,便完成了对原始数组的从小到大的排序。

(2)选择排序分析:

选择排序在对n个数据执行的过程中,无论原数据是否有顺序,都需要进行n-1步的中间排序。

优点:思路简单

缺点:执行代码优点长,效率不是很高。

效率:时间复杂度O(n^2),空间效率,只需一个辅存空间

简单选择排序,平均O(n^2),最坏O(n^2),空间O(1),不稳定

(3)选择排序代码

public class shuzuA {
     static final int SIZE=10;
     public static void main(String[] args){
          int[] shuzu=new int[SIZE];
          int i;
          for(i=0;i<SIZE;i++){
               shuzu[i]=(int)(100+Math.random()*(100+1));
          }
          System.out.println("排序前数组:");
          for(i=0;i<SIZE;i++){
               System.out.print(shuzu[i]+" ");
          }
          System.out.println();
          selectSort(shuzu);
          System.out.println("排序后数组:");
          for(i=0;i<SIZE;i++){
               System.out.print(shuzu[i]+" ");
          }
     }
     public static void selectSort(int[] a){
          int index,temp;
          for(int i=0;i<a.length-1;i++){
               index=i;
               for(int j=i+1;j<a.length;j++){//为了找到index这个索引之后的最小值的索引。
                    if(a[j]<a[index]){
                         index=j;//每次比较完,index是最小值的索引。
                    }
               }
               if(index!=i){//交换两个数
                    temp=a[i];
                    a[i]=a[index];
                    a[index]=temp;
               }
          }
     }
}

 

2:堆排序(Heap Sort基于选择排序思想的)

(1)堆排序流程

{什么是堆结构:堆结构是一种树结构,是一个完全二叉树。}

(2)堆排序分析

堆排序,平均O(nlogn),最坏O(nlogn),空间O(1),不稳定

(3)堆排序代码

public class DemoJoin{
    static final int SIZE=10;
    static void heapSort(int a[],int n){
        int i,j,h,k;
        int t;
        for(i=n/2-1;i>=0;i--){
            while(2*i+1<n)
            {
                j=2*i+1;
                if((j+1)<n){
                    if(a[j]<a[j+1])
                        j++;
                }
                if(a[i]<a[j])
                {
                    t=a[i];
                    a[i]=a[j];
                    a[j]=t;
                    i=j;
                }
                else
                    break;
            }
        }
        System.out.print("原数据构成的堆:");
        for(h=0;h<n;h++)
            System.out.print(" "+a[h]);
        System.out.println();
        for(i=n-1;i>0;i--){
            t=a[0];
            a[0]=a[i];
            a[i]=t;
            k=0;
            while(2*k+1<i){
                j=2*k+1;
                if((j+1)<i)
                {
                    if(a[j]<a[j+1])
                        j++;
                }
                if(a[k]<a[j])
                {
                    t=a[k];
                    a[k]=a[j];
                    a[j]=t;
                    k=j;
                }
                else
                    break;
            }
        }
    }

    public static void main(String[] args) {
        int[] shuzu=new int[SIZE];
        int i;
        for(i=0;i<SIZE;i++){
            shuzu[i]=(int)(100+Math.random()*(100+1));
        }
        System.out.println("排序前的数组:");
        for(i=0;i<SIZE;i++){
            System.out.print(shuzu[i]+" ");
        }
        System.out.println();

        heapSort(shuzu,SIZE);

        System.out.println("排序后的数组:");
        for(i=0;i<SIZE;i++){
            System.out.print(shuzu[i]+" ");
        }
        System.out.println();

    }


}

 

三:插入排序

1:直接插入排序(Insertion Sort)

(1)直接插入排序流程

——(1)首先对数组的前两个数据进行从小到大的排序。

——(2)接着将第3个数据与排好序的两个数据比较,将第3个数据插入到何时的位置,

——(3)然后,将第四个数据插入到已排好序的前3个数据中。

——(4)不断重复上述过程,直到把最后一个数据插入到合适的位置。最后,便完成了对原始数据从小到大的排序。

(打扑克,边抓牌,边捋牌)

(2)直接插入排序分析

插入排序算法在对N个数据进行排序时,无论原数组有无顺序,都需要进行N-1步的排序。

优点:在数组已有一定顺序的情况下,排序效率较好。

缺点:如果数据无规则,则需要移动大量的数据。其排序效率也不是很好。

效率:时间复杂度O(n^2),并且是一个稳定的排序方法。

直接插入排序,平均O(n^2),最坏O(n^2),空间O(1),稳定性

(3)直接插入排序代码

public class shuzuA {
     public static void main(String[] args){
          int[] shuzu={1,234,42,344,5,3,9};
          insertionSort(shuzu);
          for(int i=0;i<shuzu.length;i++){
               System.out.print(" "+shuzu[i]);
          }
     }
     public static void insertionSort(int[] a){
          int i;
          int j;//需要插入的位置
          int t;//要插入的数据
          int h;
          for(i=1;i<a.length;i++){
               t=a[i];//要插入的数据是a[i],新抓的牌
               j=i-1;//使需要插入的位置的在需要插入的元素的前一个
               while(j>=0&&t<a[j]){
                    a[j+1]=a[j];
                    j--;
               }
               a[j+1]=t;   //将数据t插入到正确的位置。
          }
     }
}

 

 

3:Shell排序(希尔排序/缩小增量排序)

(1)shell排序的流程

——(1)将有n个元素的数组分为n/2个数字序列,第1个数据和第n/2+1个数据为一对,......

——(2)一次循环是每一个序列对排好顺序

——(3)然后,在变为n/4个序列,在次排序

——(4)不断重复上述过程,随着序列减少最后变为一个,也就完成了整个排序。

(2)shell排序的分析

shell排序的时间复杂度是一个复杂的问题,因为shell排序的时间复杂度与步长序列有关。

(3)shell排序的代码

public class shuzuA {
     public static void main(String[] args){
          int[] shuzu={1,4,5,7,3,8,9,2};
          System.out.print("原数组为");
          for(int h=0;h<shuzu.length;h++){
               System.out.print(" "+shuzu[h]);
          }
          System.out.println();
          shellSort(shuzu);
     }
     public static void shellSort(int[] a){
          int i,j;
          int r,temp;//r为间距
          int x=0;
          for(r=a.length/2;r>=1;r/=2){//将数组元素分为多个数字序列
               for(i=r;i<a.length;i++){
                    temp=a[i];
                    j=i-r;
                    while(j>=0&&temp<a[j]){
                         a[j+r]=a[j];
                         j-=r;
                    }
                    a[j+r]=temp;
               }
               x++;
               System.out.print("第"+x+"步排序结果");
               for(int h=0;h<a.length;h++){
                    System.out.print(" "+a[h]);
               }
               System.out.println();
          }
     }
}

四:合并排序(MergeSort)

(1)合并排序的流程(通过多次的二路合并完成一遍的合并)

——(1)将N个原始数据看成N个长度为1的有序字表,这时妹子字表中只有一个元素,

将他们一次两两合并,得到长度为2的若干有序字表

——(2)经过第1次合并,得到长度为2的有序表序列,在将长度为2的有序表序列进行两

两合并。得到长度为4的有序字表

——(3)不断重复,一直到最后得到长度为N的有序字表,从而完成需过程。

(2)合并排序分析

合并排序,平均O(nlogn),最坏O(nlogn),空间O(n),稳定

(4)合并排序的代码

public class DemoJoin{
    static final int SIZE=15;
    static void mergeOne(int a[],int b[],int n,int len)
    {
        int i,j,k,s,e;
        s=0;
        while(s+len<n)
        {
            e=s+2*len-1;
            if(e>=n)
                e=n-1;
            //相邻有序段合并
            k=s;
            i=s;
            j=s+len;
            while(i<s+len&&j<=e)
            {
                if(a[i]<=a[j])
                    b[k++]=a[i++];
                else
                    b[k++]=a[j++];
            }
            while(i<s+len){
                b[k++]=a[i++];
            }
            while(j<=e)
                b[k++]=a[j++];
            s=e+1;
        }
        if(s<n)
        {
            for(;s<n;s++)
                b[s]=a[s];
        }
    }

    static void mergeSort(int a[],int n){
        int h,count,len,f;
        count=0;
        len=1;
        f=0;
        int[] p=new int[n];
        while(len<n){
            if(f==1)
                mergeOne(p,a,n,len);
            else
                mergeOne(a,p,n,len);
            len=len*2;
            f=1-f;
            count++;
            System.out.printf("第"+count+"步排序结果");
            for(h=0;h<SIZE;h++){
                System.out.printf(" "+a[h]);
            }
            System.out.println();
        }
        if(f==1){
            for(h=0;h<n;h++){
                a[h]=p[h];
            }
        }
    }
    public static void main(String[] args) {
        int[] shuzu=new int[SIZE];
        int i;
        for(i=0;i<SIZE;i++){
            shuzu[i]=(int)(100+Math.random()*(100+1));
        }
        System.out.println("排序前的数组:");
        for(i=0;i<SIZE;i++){
            System.out.print(shuzu[i]+" ");
        }
        System.out.println();
        mergeSort(shuzu,SIZE);
        System.out.println("排序后的数组:");
        for(i=0;i<SIZE;i++){
            System.out.print(shuzu[i]+" ");
        }
        System.out.println();
    }


}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值