基础排序java实现

需要掌握的基础排序

一、插入排序  1)直接插入排序2)希尔排序   

二、交换排序  1)冒泡排序2)快速排序

三、选择排序  1)简单选择排序2)堆排序

四、归并排序

一、插入排序

  简单的理解就是遍历整个数组,在过程中对每个数都跟前面进行比较只要比它小就往前挪。

  1) 直接插入排序实现

      public static void directInsert(int [] data)
      {
          int temp=0;
          int len=data.length;
          for(int i=1;i<len;i++)
          {
              temp=data[i];
              int j=i-1;
              while(j>-1 && temp<data[j])
              {
                  data[j+1]=data[j];
                  j--;
              }
              data[j+1]=temp;
          }
      }

  2)希尔排序

  理解:http://blog.csdn.net/morewindows/article/details/6668714

  按照n/2,n/4,n/8,,,,1的间隔对数组进行直接插入排序。当数组基本有序时,插入排序比较的次数最少,间隔为1的时候基本有序,最后一次执行插入排序效果最好。

    public static void shellInsert(int [] data)
    {
        int temp=0;
        int len=data.length;
        for(int gap=len/2;gap>0;gap/=2)//最外围的缩小增量
        {
            for(int i=gap;i<len;i++)//间隔排序比如13579    246810  这样的等间隔分组   直接插入排序
            {
                temp=data[i];
                int j=i-gap;
                while(j>-1 && temp<data[j])
                {
                    data[j+gap]=data[j];
                    j-=gap;
                }
                data[j+gap]=temp;
                System.out.println(Arrays.toString(data));
            }
        }
    }

二、交换排序

  1)冒泡排序

  相邻的两个数比较大小,直到交换完成。

  第一趟把最大的数换到了最右边,第二趟第二大的换到了倒数第二个,每次对前n-i个数进行排序。

      public static void bubble(int [] data)
      {
          int len=data.length;
          int cnt=0;//交换次数。假如为0,排序完成跳出
          int temp=0;
          for(int i=1;i<len;i++)//进行n-1趟排序
          {
              for(int j=0;j<len-i;j++)
              {
                  if(data[j]>data[j+1])
                  {
                      temp=data[j];
                      data[j]=data[j+1];
                      data[j+1]=temp;
                      cnt++;
                  }
              }
              if(cnt==0)
                  break;
              cnt=0;
          }
      }

  2)快速排序

  选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

      

    public static void quickSort(int [] data,int left,int right)
    {
        if(left<right)
        {
            int middle=getMiddle(data, left,right);//获取中间位置
            quickSort(data, left, middle-1);//左边排序
            quickSort(data, middle+1, right);//右边排序
        }
    }
    public static int getMiddle(int [] data,int left,int right)
    {
        int pivot=data[left];//以左边为基准数
        while(left<right)//假如左小于右
        {
            while(left<right && data[right]>pivot)//先在右边找出一个小于基准数的数让在最左边
            {
                right--;
            }
            data[left]=data[right];
            while(left<right && data[left]<pivot)//再在左边找出一个大于基准数的数放在right的位置上
            {
                left++;
            }
            data[right]=data[left];
        }
        data[left]=pivot;//当left==right相等时跳出,然后将基准数放在这个地方
        return left;
    }

三、选择排序

  1)简单选择排序

  选择排序总共需要n-1次遍历,每次排序都找出最小的值。

      public static void selectSort(int [] data)
      {
          int len=data.length;
          for(int i=0;i<len-1;i++)//n-1次排序
          {
              int min=i;
              for(int j=i+1;j<len;j++)//找出是否存在最小值,且比data[i]小
              {
                  if(data[j]<data[min])
                      min=j;
              }
              if(min!=i)//假如有,替换
              {
                  int temp=data[i];
                  data[i]=data[min];
                  data[min]=temp;
              }
          }
      }

  2)堆排序

四、归并排序

  1)归并排序

  参考:http://blog.csdn.net/pzhtpf/article/details/7560312

  归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

  

      //递归实现
      public static void mergeSort(int [] data,int low,int high)
      {
          int middle=(low+high)/2;
          if(low<high)
          {
              mergeSort(data, low, middle);
              mergeSort(data, middle+1, high);
              merge(data, low, middle, high);
          }
      }
      
      public static void merge(int []data,int low ,int middle,int high)
      {
          int temp[]=new int[high-low+1];
          int i=low;
          int j=middle+1;
          int k=0;
          while(i<=middle && j<=high)   //将分块中排好序  每上一层就是将两个排好序的进行归并
          {
              if(data[i]<data[j])
              {
                  temp[k++]=data[i++];
              }
              else 
              {
                  temp[k++]=data[j++];
            }
          }
          while(i<=middle)
          {
              temp[k++]=data[i++];
          }
          while(j<=high)
          {
              temp[k++]=data[j++];
          }
          for(int m=0;m<k;m++)
          {
              data[low++]=temp[m];
          }
      }

总结

  各种内部排序方法的性能比较

方法平均时间最坏情况辅助存储
简单排序 O(n^2) O(n^2) O(1)
快速排序 O(nlogn) O(n^2) O(nlogn)
堆排序 O(nlogn) O(nlogn) O(1)
归并排序 O(nlogn) O(nlogn) O(n)

结论:

1)从平均时间而言:快速排序最佳,最坏情况可能不如堆排序和归并排序

2)从算法简单性看:由于直接选择排序、直接插入排序和冒泡排序的算法比较简单,认为是简单排序,都包含在上图中的“简单排序”。对于希尔排序、快速排序、堆排序、归并排序是复杂排序。

3)从稳定性看:直接插入排序、冒泡排序和归并排序是稳定的;而希尔排序、直接选择排序、快速排序和堆排序是不稳定的。

4)从规模看:当n较小时,宜采用简单排序;当n较大时,宜采用改进排序。

综合来看

1)当n较大时,若要求排序稳定,则采用归并排序

2)当n较大,关键字分布随机,且不要求稳定,则采用快速排序

3)当n较大,关键字会出现正逆序情形,可采用堆排序或者归并排序

4)当n较小,记录已接近有序或者随机分布,又要求排序稳定,可采用直接插入排序

5)当n较小,不要求稳定,可采用直接选择排序

原文地址:https://www.cnblogs.com/maydow/p/4789866.html