将数组封装在类中:
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 }
二、选择排序
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 }
三、插入排序
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 }
测试用类:
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 }
四、对象排序
对象排序一般通过两种方法实现:
(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 }
(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 }
五、归并排序
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
(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 }
(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 }
归并排序算法分析:
归并排序的形式就是一棵二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的可以得出它的时间复杂度是O(n*log2n)。
空间复杂度
由前面的算法说明可知,算法处理过程中,需要一个大小为n的临时存储空间用以保存合并序列。
在归并排序中,相等的元素的顺序不会改变,所以它是稳定的算法。