排序算法 Java实现代码

openkk 12年前

JAVA下面的 堆排序  冒泡排序法 选择排序法 快速排序法 插入排序法 折半插入排序法 希尔排序法 归并排序法

/**   *   * @param <T>   */  public class Sort<T extends Comparable<T>> {   //交换索引i和索引j的值   private void swap(T[] data,int i,int j){    T tmp;    tmp = data[i];    data[i] = data[j];    data[j] = tmp;   }      //-----堆排序 时间复杂度O(nlogn)-----   public void heapSort(T[] data) {    int arrayLength = data.length;    // 循环建堆    for (int i = 0; i < arrayLength - 1; i++) {     // 建堆     builMaxdHeap(data, arrayLength - 1 - i);     // 交换堆顶和最后一个元素     swap(data, 0, arrayLength - 1 - i);     //System.out.println(java.util.Arrays.toString(data));    }   }     // 对data数组从0到lastIndex建大顶堆   private void builMaxdHeap(T[] data, int lastIndex) {    // 从lastIndex处节点(最后一个节点)的父节点开始    for (int i = (lastIndex - 1) / 2; i >= 0; i--) {     // k保存当前正在判断的节点     int k = i;     // 如果当前k节点的子节点存在     while (k * 2 + 1 <= lastIndex) {      // k节点的左子节点的索引      int biggerIndex = 2 * k + 1;      // 如果biggerIndex小于lastIndex,即biggerIndex + 1      // 代表的k节点的右子节点存在      if (biggerIndex < lastIndex) {       // 如果右子节点的值较大       if (data[biggerIndex].compareTo(data[biggerIndex + 1]) < 0) {        // biggerIndex总是记录较大子节点的索引        biggerIndex++;       }      }      // 如果k节点的值小于其较大子节点的值      if (data[k].compareTo(data[biggerIndex]) < 0) {       // 交换它们       swap(data, k, biggerIndex);       // 将biggerIndex赋给k,开始while循环的下一次循环,       // 重新保证k节点的值大于其左、右子节点的值。       k = biggerIndex;      } else {       break;      }     }    }   }      //-----冒泡排序法 时间复杂度O(n^2)-----   public void bubbleSort(T[] data){       int i,j;    for(i=0;i<data.length-1;i++){     for(j=0;j<data.length-i-1;j++){      //排序之前[9, -16*, 21, 23, -30, -49, 21*, 30, 30]      //排序之后[-49, -30, -16*, 9, 21, 21*, 23, 30, 30]      if(data[j].compareTo(data[j+1]) > 0){       swap(data,j+1,j);      }     }    }   }      //-----选择排序法 时间复杂度O(n^2)-----   public void selectSort(T[] data){    int i,j;         for(i=0;i<data.length-1;i++){     for(j=i+1;j<data.length;j++){      //排序之前[9, -16*, 21, 23, -30, -49, 21*, 30, 30]      //排序之后[-49, -30, -16*, 9, 21, 21*, 23, 30, 30]      if (data[i].compareTo(data[j]) > 0){       swap(data,i,j);      }     }    }   }      //-----快速排序法  时间复杂度为O(log2n)-----   public void quickSort(T[] data){    subQuickSort(data,0,data.length-1);   }      private void subQuickSort(T[] data,int start,int end){    if( start < end ){     //以第一个元素作为分界值     T base = data[start];     //i从左边开始搜索大于分界值元素的索引     int i = start;     //j从右边开始搜索小于分界值元素的索引     int j = end + 1;     //排序之前[9, -16*, 21, 23, -30, -49, 21*, 30, 30]     //排序之后[-30, -16*, -49, 9, 21*, 21, 23, 30, 30]     while(true){      //左边跳过比base小的元素      while(i < end && data[++i].compareTo(base) <= 0);      //右边跳过比base大的元素      while(j > start && data[--j].compareTo(base) >= 0);            if(j > i){       swap(data,i,j);      }else{       break;      }     }     //将分界值还原     swap(data,start,j);          //递归左边序列     subQuickSort(data,start,j-1);     //递归右边序列     subQuickSort(data,j+1,end);     // System.out.println(  Arrays.toString(data) );    }   }      //-----插入排序法 时间复杂度O(n^2)-----   public void insertSort(T[] data){    int arrayLength = data.length;        for(int i=1;i<arrayLength;i++){     //当整体后移时保证data[i]的值不会丢失     T tmp = data[i];     //i索引处的值已经比前面所有值都大,表明已经有序,无需插入     //i-1处索引之前的数值已经有序,i-1处索引处元素的值也是最大值     if(data[i].compareTo(data[i-1]) < 0){      int j = i-1;      //整体后移一个      while(j>=0 && data[j].compareTo(tmp) > 0){       data[j+1] = data[j];       j--;      }     data[j+1] = tmp;     // System.out.println(  Arrays.toString(data) );     }    }   }      //-----折半插入排序法 时间复杂度-----   public void binaryInsertSort(T[] data) {    int arrayLength = data.length;      for (int i = 1; i < arrayLength; i++) {     if (data[i - 1].compareTo(data[i]) > 0) {      // 缓存i处的元素值      T tmp = data[i];        // 记录搜索范围的左边界      int low = 0;      // 记录搜索范围的右边界      int high = i - 1;        while (high >= low) {       // 记录中间位置       int mid = (high + low) / 2;       // 比较中间位置数据和i处数据大小,以缩小搜索范围         if (tmp.compareTo(data[mid]) > 0) {        low = mid + 1;       } else {        high = mid - 1;       }      }      // 将low~i处数据整体向后移动1位      for (int j = i; j > low; j--) {       data[j] = data[j - 1];      }      data[low] = tmp;       }     //System.out.println(  Arrays.toString(data) );    }   }      //-----希尔排序法 时间复杂度O(nlogn)O(n^2)具体看h的值-----   public void shellSort(T[] data){    int arrayLength = data.length;    //h保存可变增量        int h = 1;    while(h<=arrayLength/3){     h = h * 3 + 1;     //System.out.println("h="+h);    }        while(h > 0){     //System.out.println(Arrays.toString( data )+"h="+h);          for(int i=h;i<arrayLength;i++){      //当整体后移时,保证data[i]的值不丢失      T tmp = data[i];      //i索引处的值已经比前面所有的值大      //(i-1索引之前的值已经有序的,i-1索引处元素的值就是最大值)      if(data[i].compareTo(data[i-h]) < 0){       int j = i-h;       //整体后移一格       while(j>=0 && data[j].compareTo(tmp) > 0){        data[j+h] = data[j];        j-=h;       }              //最后将tmp值插入合适的位置       data[j+h] = tmp;      }     }     h = (h-1)/3;    }       }      //-----归并排序法 时间复杂度为O(nlog2n)-----   public void mergeSort(T[] data){    subMergeSort(data,0,data.length-1);   }      private void subMergeSort(T[] data,int left,int right){    if(right > left){     //找出中间索引     //System.out.println(  Arrays.toString(data) );     int center = (left + right)/2;     //对左边数组进行递归     subMergeSort(data,left,center);     //对右边数组进行递归     subMergeSort(data,center+1,right);     //合并     merge(data,left,center,right);    }   }      @SuppressWarnings("unchecked")   private void merge(T[] data, int left, int center, int right) {    Object[] tmpArr = new Object[data.length];    int mid = center + 1;    // third记录中间处索引    int third = left;    int tmp = left;      while (left <= center && mid <= right) {     // 从两个数组中取出最小的放入中间数组     if (data[left].compareTo(data[mid]) <= 0) {      tmpArr[third++] = data[left++];     } else {      tmpArr[third++] = data[mid++];     }    }        // 剩余部分依次放入中间数组    while (mid <= right) {     tmpArr[third++] = data[mid++];    }    while (left <= center) {     tmpArr[third++] = data[left++];    }        // 将中间数组的内容复制拷回原数组    // (原left~right范围内德内容被复制回原数组)    while (tmp <= right) {     data[tmp] = (T) tmpArr[tmp++];    }     }        /*public static void main(String[] args){    DataWarp[] dataWarp = {     new DataWarp(9,""),     new DataWarp(-16,"*"),     new DataWarp(21,""),     new DataWarp(23,""),     new DataWarp(-30,""),     new DataWarp(-49,""),     new DataWarp(21,"*"),     new DataWarp(30,""),     new DataWarp(56,""),     new DataWarp(40,""),     new DataWarp(430,""),     new DataWarp(-67,""),     new DataWarp(56,""),     new DataWarp(-87,""),     new DataWarp(26,""),     new DataWarp(92,""),     new DataWarp(30,"")    };        DataWarp[] dataWarp2 = {      new DataWarp(9,""),      new DataWarp(-16,"*"),      new DataWarp(21,""),      new DataWarp(23,""),      new DataWarp(-30,""),      new DataWarp(-49,""),      new DataWarp(21,"*"),      new DataWarp(30,""),      new DataWarp(56,""),      new DataWarp(40,""),      new DataWarp(430,""),      new DataWarp(-67,""),      new DataWarp(56,""),      new DataWarp(-87,""),      new DataWarp(26,""),      new DataWarp(92,""),      new DataWarp(30,"")     };           System.out.println( "排序之前" + Arrays.toString(dataWarp) );              Sort<DataWarp> sort = new Sort<DataWarp>();       sort.mergeSort(dataWarp);       sort.shellSort(dataWarp2);              System.out.println( "排序之后" + Arrays.toString(dataWarp) );       System.out.println( "排序之后" + Arrays.toString(dataWarp2) );     }*/  }