• 数据结构之简单排序算法


    将数组封装在类中:

    1 private int[] arr;//封装的内容包括:数组和数组的长度
    2     private int len;
    3     public BubbleSortArray(int maxSize){
    4         arr=new int[maxSize];
    5         len=0;
    6     }

    类中的一些方法:

     1 public void insert(int value){//数组中插入元素
     2         arr[len]=value;
     3         len++;
     4     }
     5     public  void display(){
     6         for(int i=0;i<len;i++){
     7             System.out.print(arr[i]+" ");
     8         }
     9         System.out.println();
    10     }
    11 public  void swap(int[] arr2, int i, int j) {
    12         int temp=arr2[i];
    13         arr2[i]=arr2[j];
    14         arr2[j]=temp;
    15     }
    16     public int length(){
    17         return len;
    18     }

    一、冒泡排序

    1 public void method_Bubble(){//冒泡排序
    2         for(int i=0;i<len-1;i++){
    3             for(int j=i+1;j<len;j++){
    4                 if(arr[i]>arr[j]){
    5                     swap(arr,i,j);
    6                 }
    7             }
    8         }
    9     }
    View Code

    二、选择排序

     1     public void method_select(){//选择排序
     2         int flag;
     3         for(int i=0;i<len-1;i++){
     4             flag=i;
     5             for(int j=i+1;j<len;j++){
     6                 if(arr[j]<arr[flag]){
     7                     flag=j;
     8                 }
     9             }
    10             if(flag!=i){
    11                 swap(arr, i, flag);
    12             }
    13         }
    14     }
    View Code

    三、插入排序

     1     public void method_insert(){//插入排序
     2         int temp,j;
     3         for(int i=1;i<len;i++){
     4             temp=arr[i];
     5             j=i;
     6             while(j>0&&arr[j]>=temp){
     7                 arr[j]=arr[j-1];
     8                 j--;
     9             }
    10             arr[j]=temp;
    11         }
    12     }
    View Code

    测试用类:

     1 public class SortMethod {
     2 
     3     /**
     4      * @param args
     5      */
     6     /*
     7      * 练习集中常见的排序算法,冒泡排序、选择排序、插入排序,我们把要排序的数组封装成数组对象
     8      */
     9     public static void main(String[] args) {
    10         int maxSize=100;
    11         BubbleSortArray arr=new BubbleSortArray(maxSize);
    12         arr.insert(100);
    13         arr.insert(50);
    14         arr.insert(54);
    15         arr.insert(25);
    16         arr.insert(63);
    17         arr.insert(78);
    18         arr.insert(23);
    19         arr.insert(12);
    20         arr.insert(6);
    21         arr.insert(99);
    22         arr.display();
    23 //        arr.method_Bubble();
    24 //        arr.method_select();
    25         arr.method_insert();
    26         arr.display();
    27         System.out.println(arr.length());
    28     }
    29 
    30 }
    View Code

     四、对象排序

    对象排序一般通过两种方法实现:

    (1)让元素自身具备比较性,需要元素对象,实现Comparable接口,覆盖compareTo方法

     1 package patten.design;
     2 
     3 class Cat implements Comparable {
     4 
     5     private int hight;
     6     private int weight;
     7 
     8     public Cat(int hight, int weight) {
     9         super();
    10         this.hight = hight;
    11         this.weight = weight;
    12     }
    13 
    14     public int getHight() {
    15         return hight;
    16     }
    17 
    18     public void setHight(int hight) {
    19         this.hight = hight;
    20     }
    21 
    22     public int getWeight() {
    23         return weight;
    24     }
    25 
    26     public void setWeight(int weight) {
    27         this.weight = weight;
    28     }
    29 
    30     @Override
    31     public int compareTo(Object o) {// 按身高进行排序,身高相同则按体重进行排序
    32         if (o instanceof Cat) {
    33             Cat c = (Cat) o;
    34             int temp = this.getHight() - c.getHight();
    35             return temp == 0 ? this.getWeight() - c.getWeight() : temp;
    36         }
    37         return 0;
    38     }
    39 
    40     @Override
    41     public String toString() {
    42         return "Cat [hight=" + hight + ", weight=" + weight + "]";
    43     }
    44 
    45 }
    46 
    47 //定义排序类
    48 class DataSort {
    49     public static void sort(Object o[]) {
    50         for (int i = 0; i < o.length - 1; i++) {
    51             for (int j = i + 1; j < o.length; j++) {
    52                 Comparable c1 = (Comparable) o[i];
    53                 Comparable c2 = (Comparable) o[j];
    54                 if (c1.compareTo(c2) == 1) {
    55                     swap(o, i, j);
    56                 }
    57             }
    58         }
    59     }
    60 
    61     public static void swap(Object[] o, int i, int j) {
    62         Object tempObject;
    63         tempObject = o[i];
    64         o[i] = o[j];
    65         o[j] = tempObject;
    66     }
    67 
    68     public static void getResult(Object[] o) {
    69         for (int j = 0; j < o.length; j++) {
    70             System.out.println(o[j].toString());
    71         }
    72     }
    73 
    74 }
    75 
    76 public class ComparableInterface {
    77 
    78     /**
    79      * @param args
    80      */
    81     public static void main(String[] args) {
    82         Cat cat[] = { new Cat(5, 5), new Cat(2, 3), new Cat(2, 2) };
    83         DataSort.sort(cat);
    84         DataSort.getResult(cat);
    85     }
    86 
    87 }
    View Code

     (2)定义一个实现了ComParator接口的比较器,覆盖compare方法,实现对象的自定义比较器以及比较逻辑排序方式,使得对象排序更加灵活

    【温情提示】:在这里我们实现Comparator进行定制排序,还是要实现Comparable接口的,但是在做调用compareTo方法的时候,把比较工作交给了具体的比较器,如果使用Collection去存储对象元素是,则可以将实现了comparator接口的比较器对象传递给对应类的构造函数,再调用Collections工具类的sort()方法进行排序。比如我们使用Treeset集合进行对象的存储,则可以用下面的方式来实现:

    Treeset treeset= new Treeset(new CompareByHeight());//按照对象的某一个属性进行比较,当新的对象要添加进treeset集合时,就会调用对应的比较器对集合元素进行相应的操作.

    真实工作中我们一般都是用封装好的sort方法,如Collections.sort(treeset),Arrays.sort(cat)进行排序等等,只要集合中的对象都实现了Comparable接口即可

    具体代码实现:

      1 package patten.design;
      2 
      3 import java.util.Comparator;
      4 
      5 class Cat_2 implements Comparable {
      6 
      7     private int hight;
      8     private int weight;
      9     //这里把比较器作为类的成员变量,实现对象的定制排序
     10 //    private Comparator comparator = new CompareByWeight();
     11     private Comparator comparator=new CompareByHight();
     12 
     13     public Cat_2(Comparator comparator) {
     14         super();
     15         this.comparator = comparator;
     16     }
     17 
     18     public Comparator getComparator() {
     19         return comparator;
     20     }
     21 
     22     public void setComparator(Comparator comparator) {
     23         this.comparator = comparator;
     24     }
     25 
     26     public Cat_2(int hight, int weight) {
     27         super();
     28         this.hight = hight;
     29         this.weight = weight;
     30     }
     31 
     32     public int getHight() {
     33         return hight;
     34     }
     35 
     36     public void setHight(int hight) {
     37         this.hight = hight;
     38     }
     39 
     40     public int getWeight() {
     41         return weight;
     42     }
     43 
     44     public void setWeight(int weight) {
     45         this.weight = weight;
     46     }
     47 
     48     //重写类的toString()方法
     49     @Override
     50     public String toString() {
     51         return "Cat [hight=" + hight + ", weight=" + weight + "]";
     52     }
     53 
     54     @Override
     55     public int compareTo(Object o) {
     56 
     57         //实现定制排序
     58 //        return comparator.compare(this, o);
     59         return comparator.compare(this, o);
     60     }
     61 
     62 }
     63 
     64 //定义进行排序的功能类实现
     65 class DataSort_2 {
     66     public static void sort(Object o[]) {
     67         for (int i = 0; i < o.length - 1; i++) {
     68             for (int j = i + 1; j < o.length; j++) {
     69                 Comparable c1 = (Comparable) o[i];
     70                 Comparable c2 = (Comparable) o[j];
     71                 if (c1.compareTo(c2) == 1) {
     72                     swap(o, i, j);
     73                 }
     74             }
     75         }
     76     }
     77 
     78     public static void swap(Object[] o, int i, int j) {
     79         Object tempObject;
     80         tempObject = o[i];
     81         o[i] = o[j];
     82         o[j] = tempObject;
     83     }
     84 
     85     //获取对象数组的内容
     86     public static void getResult(Object[] o) {
     87         for (int j = 0; j < o.length; j++) {
     88             System.out.println(o[j].toString());
     89         }
     90     }
     91 
     92 }
     93 
     94 class CompareByHight implements Comparator {
     95 
     96     @Override
     97     public int compare(Object o1, Object o2) {
     98         Cat_2 c1 = (Cat_2) o1;
     99         Cat_2 c2 = (Cat_2) o2;
    100         if (c1.getHight() > c2.getHight()) {
    101             return 1;
    102         } else if (c1.getHight() < c2.getHight()) {
    103             return -1;
    104         } else {
    105             return 0;
    106         }
    107     }
    108 
    109 }
    110 
    111 class CompareByWeight implements Comparator {
    112 
    113     @Override
    114     public int compare(Object o1, Object o2) {
    115         Cat_2 c1 = (Cat_2) o1;
    116         Cat_2 c2 = (Cat_2) o2;
    117         if (c1.getWeight() > c2.getWeight()) {
    118             return 1;
    119         } else if (c1.getWeight() < c2.getWeight()) {
    120             return -1;
    121         } else {
    122             return 0;
    123         }
    124     }
    125 
    126 }
    127 
    128 public class ComparatorTest {
    129 
    130     /**
    131      * @param args
    132      */
    133     public static void main(String[] args) {
    134 
    135         Cat_2 cat[] = { new Cat_2(5, 5), new Cat_2(2, 3), new Cat_2(2, 1) };
    136         DataSort_2.sort(cat);
    137         DataSort_2.getResult(cat);
    138     }
    139 
    140 }
    View Code

    五、归并排序

    归并排序是建立在归并操作上的一种有效的排序算法,将两个或者两个以上的有序表组合成一个有序的新表。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

    将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并

    (1)归并排序实现数组归并:

    用到的三个数组:

    int arrA[] = { 1, 3, 5, 7, 9 };
    int arrB[] = { 2, 4, 6, 8, 10 };
    int arrC[] = new int[arrA.length + arrB.length];
    Merge(arrA, arrA.length, arrB, arrB.length, arrC, arrC.length);

    实现归并的函数实现:

     1     // 归并排序实现两个数组的归并,白两个有序的数组A和B归并至数组C
     2     public static void Merge(int[] arrA, int sizeA, int[] arrB, int sizeB,
     3             int[] arrC, int sizeC) {
     4         int adex = 0;
     5         int bdex = 0;
     6         int cdex = 0;
     7         while (adex < sizeA && bdex < sizeA) {
     8             if (arrA[adex] <= arrB[bdex]) {
     9                 arrC[cdex++] = arrA[adex++];
    10             } else {
    11                 arrC[cdex++] = arrB[bdex++];
    12             }
    13         }
    14         while (adex < sizeA) {
    15             arrC[cdex++] = arrA[adex++];
    16         }
    17         while (bdex < sizeB) {
    18             arrC[cdex++] = arrB[bdex++];
    19         }
    20         display(arrC);
    21     }
    View Code

    (2)通过归并进行排序

    归并排序其实要做两件事:

    (1)分解:将一个数组进行分解得到小的序列,对每个小序列进行排序

    (2)归并:排好序的小序列进行归并

    具体代码实现:

      1 package data.struct.algorithm;
      2 
      3 //把待排序的数组封装在类中
      4 class DataArr {
      5     private int arr[];
      6     private int nItems;
      7 
      8     public DataArr(int maxSize) {
      9         arr = new int[maxSize];
     10         nItems = 0;
     11     }
     12 
     13     // 向数组中添加元素
     14     public void insert2Arr(int data) {
     15         arr[nItems++] = data;
     16     }
     17 
     18     // 主函数可见调用的方法,用于产生和待排序数组相同大小的工作空间数组
     19     public void mergeSort() {
     20         int workPlace[] = new int[nItems];
     21         // 对外隐藏执行归并排序的函数
     22         rcMergeSort(workPlace, 0, nItems - 1);
     23     }
     24 
     25     public void displayArr() {
     26         for (int j = 0; j < arr.length; j++) {
     27             System.out.print(arr[j] + " ");
     28         }
     29         System.out.println();
     30     }
     31 
     32     // 执行归并操作的函数
     33     public void rcMergeSort(int workPlace[], int lowerBound, int higherBound) {
     34         if (lowerBound == higherBound) {
     35             return;
     36         } else {
     37             int mid = (lowerBound + higherBound) / 2;
     38             // 对分割开的数组的两部分进行排序
     39             rcMergeSort(workPlace, lowerBound, mid);
     40             rcMergeSort(workPlace, mid + 1, higherBound);
     41             // 把排好序的两部分归并在一起,将arr[s..m]和arr[m+1..t]归并成arr[s..t]
     42             merge(workPlace, lowerBound, mid + 1, higherBound);
     43         }
     44     }
     45 
     46     // 归并两个有序的部分,三个参数的含义(数组工作空间、第一个部分的开始索引、第二部分开始索引、第二部分结束索引)
     47     public void merge(int workPlace[], int lowerPtr, int highPtr, int highBound) {
     48         // 记录归并开始的地方,方便后面的复制操作
     49         int lowerBound = lowerPtr;
     50         // 中间值的索引
     51         int mid = highPtr - 1;
     52         // 工作数组空间的索引(workPlace)
     53         int j = 0;
     54         // 数组的大小
     55         int n = highBound - lowerBound + 1;
     56         while (lowerPtr <= mid && highPtr <= highBound) {
     57             if (arr[lowerPtr] <= arr[highPtr]) {
     58 
     59                 workPlace[j++] = arr[lowerPtr++];
     60             } else {
     61                 workPlace[j++] = arr[highPtr++];
     62             }
     63         }
     64         while (lowerPtr <= mid) {
     65             workPlace[j++] = arr[lowerPtr++];
     66         }
     67         while (highPtr <= highBound) {
     68             workPlace[j++] = arr[highPtr++];
     69         }
     70         // 将排好序的数组空间的内容复制到原数组中,这点区别于我们用第三个数组作为存储空间存放归并好的两个有序数组
     71         for (j = 0; j < n; j++) {
     72             arr[lowerBound + j] = workPlace[j];
     73         }
     74     }
     75 }
     76 
     77 public class MergeSortTest {
     78 
     79     /**
     80      * @param args
     81      */
     82     public static void main(String[] args) {
     83         DataArr dArr = new DataArr(11);
     84         // 数组中插入一些元素
     85         dArr.insert2Arr(3);
     86         dArr.insert2Arr(8);
     87         dArr.insert2Arr(33);
     88         dArr.insert2Arr(35);
     89         dArr.insert2Arr(90);
     90         dArr.insert2Arr(14);
     91         dArr.insert2Arr(980);
     92         dArr.insert2Arr(67);
     93         dArr.insert2Arr(23);
     94         dArr.insert2Arr(39);
     95         dArr.insert2Arr(13);
     96         System.out.println("排序前");
     97         dArr.displayArr();
     98         System.out.println("-----分割线-----");
     99         // 把创建工作数组空间的任务放在了mergeSort()函数中,因为如果把这个动作放在rcMergeSort中的话,函数递归调用
    100         // 会反复创建工作空间
    101         dArr.mergeSort();
    102         System.out.println("排序后");
    103         dArr.displayArr();
    104     }
    105 }
    View Code

    归并排序算法分析:

    时间复杂度

    归并排序的形式就是一棵二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的可以得出它的时间复杂度是O(n*log2n)。

    空间复杂度

    由前面的算法说明可知,算法处理过程中,需要一个大小为n的临时存储空间用以保存合并序列。

    算法稳定性

    在归并排序中,相等的元素的顺序不会改变,所以它是稳定的算法。

  • 相关阅读:
    函数节流和防抖
    前端优化
    webpack模块
    link和@import的区别
    BFC--CSS
    javaoop_破解jdbc
    javaoop反射
    java-oop集合与泛型
    java中几个小遗漏
    java异常处理和日志管理
  • 原文地址:https://www.cnblogs.com/ysw-go/p/5349428.html
Copyright © 2020-2023  润新知