java中各种经典排序(冒泡 选择 插入 希尔等)

  1 import java.util.Arrays;
  2 
  3 public class ArraySort {
  4     public static void main(String[] args) {
  5         int[] arr = { 12, 23, 14, 5, 64, 35, 42 };
  6         System.out.println("排序前:");
  7         System.out.println(Arrays.toString(arr));
  8         // bubbleSort(arr);
  9         // selectSort(arr);
 10         // selectSort_2(arr);
 11         // insertSort(arr);
 12         // insertSort_2(arr);
 13         shellSort(arr);
 14         System.out.println("排序后:");
 15         System.out.println(Arrays.toString(arr));
 16     }
 17 
 18     /**
 19      * 冒泡排序 重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
 20      * 走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
 21      * 
 22      * @param arr
 23      */
 24     public static void bubbleSort(int[] arr) {
 25         for (int i = 0; i < arr.length - 1; i++) {
 26             boolean flag = true;// 定义一个flag标记,用于判断当有序之后就跳出循环,减少外层循环次数。
 27             for (int j = 0; j < arr.length - 1 - i; j++) {
 28                 if (arr[j] > arr[j + 1]) {
 29                     swap(arr, j, j + 1);
 30                     flag = false;
 31                 }
 32             }
 33             if (flag) {
 34                 break;
 35             }
 36         }
 37     }
 38 
 39     /**
 40      * 选择排序 每一次从待排序的数据元素中选出最小(或最大)的一个元素, 存放在序列的起始位置,直到全部待排序的数据元素排完。
 41      * 
 42      * @param arr
 43      * @param a
 44      * @param b
 45      */
 46     public static void selectSort(int[] arr) {
 47         for (int i = 0; i < arr.length - 1; i++) {
 48             for (int j = i + 1; j < arr.length; j++) {
 49                 if (arr[i] > arr[j]) {
 50                     swap(arr, i, j);
 51                 }
 52             }
 53         }
 54     }
 55 
 56     /**
 57      * 选择排序2 效率高
 58      * 
 59      * @param arr
 60      */
 61     public static void selectSort_2(int[] arr) {
 62         for (int i = 0; i < arr.length - 1; i++) {
 63             int num = arr[i];
 64             int index = i;
 65             for (int j = i + 1; j < arr.length; j++) {
 66                 if (num > arr[j]) {// 把遇到的小的值给num,角标给index,只要index发生了改变
 67                     num = arr[j]; // 则代表需要交换
 68                     index = j;
 69                 }
 70 
 71             }
 72             if (index != i) {
 73                 swap(arr, i, index);
 74             }
 75         }
 76     }
 77 
 78     /**
 79      * 插入排序 插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。
 80      * 插入排序方法分直接插入排序和折半(二分)插入排序两种
 81      * 
 82      * @param arr
 83      * @param a
 84      * @param b
 85      */
 86     public static void insertSort(int[] arr) {
 87         for (int i = 1; i < arr.length; i++) {
 88             if (arr[i - 1] > arr[i]) {
 89                 int temp = arr[i];// 待插入的元素
 90                 int j = i;
 91                 while (j > 0 && arr[j - 1] > temp) {// 将大于temp的往后移一位
 92                     arr[j] = arr[j - 1];
 93                     j--;
 94                 }
 95                 arr[j] = temp;
 96             }
 97         }
 98     }
 99 
100     /**
101      * 二分插入排序 二分法插入排序的思想和直接插入一样,只是找合适的插入位置的方式不同, 这里是按二分法找到合适的位置,可以减少比较的次数。
102      * 
103      * @param arr
104      */
105     public static void insertSort_2(int[] arr) {
106         for (int i = 0; i < arr.length; i++) {
107             int temp = arr[i];
108             int left = 0;
109             int right = i - 1;
110             int mid = 0;
111             while (left <= right) {
112                 mid = (left + right) / 2;
113                 if (temp < arr[mid]) {
114                     right = mid - 1;
115                 } else {
116                     left = mid + 1;
117                 }
118             }
119             for (int j = i - 1; j >= left; j--) {
120                 arr[j + 1] = arr[j];
121             }
122             if (left != i) {
123                 arr[left] = temp;
124             }
125         }
126     }
127 
128     /**                        希尔排序
129      *  希尔排序(Shell Sort)是插入排序的一种 思想: 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。
130      * 所有距离为dl的倍数的记录放在同一个组中。 先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,
131      * 直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
132      * 
133      * 
134      *             //从大到小
135      * @param arr
136      * @param a
137      * @param b
138      */
139 public static void shellSort(int[] arr) { 140 int j = 0; 141 int temp = 0; 142 for (int increment = arr.length / 2; increment > 0; increment /= 2) { 143 for (int i = increment; i < arr.length; i++) { 144 temp = arr[i]; 145 for (j = i; j >= increment; j -= increment) { 146 if (temp > arr[j - increment]) { 147 arr[j] = arr[j - increment]; 148 } else { 149 break; 150 } 151 } 152 arr[j] = temp; 153 } 154 } 155 } 156   
 1                 //从小到大排序
 2     public static void shellSort_2(int[] arr) {
 3 
 4         int j;
 5         int len = arr.length;
 6         for (int val = len >> 1; val > 0; val >>= 1) {//len>>1即len/2
 7             // 下面是对本次的所有分组做直接插入排序
 8             for (int i = val; i < len; i++) {
 9                 int temp = arr[i];
10                 /*
11                  * 为什么每次都用temp比较呢? 因为直接插入就是找到temp的合适位置。
12                  * 为什么temp<arr[j-val]这个条件可以放在for内呢? 因为原来的组内数据已经有序,找到位置就停止便是。
13                  * 不甚理解的去看直接插入排序吧。
14                  */
15                 for (j = i; j >= val && temp < arr[j - val]; j -= val) {
16                     /*
17                      * 为什么是arr[j-val]不是arr[j]呢?
18                      * 因为j=i开始的,而且条件是j>=val&&temp<arr[j-val]
19                      */
20                     arr[j] = arr[j - val];
21                 }
22                 /*
23                  * 注意不是arr[i] = temp 直接插入排序也是这样的。 为什么呢? 因为j是位置,i是待插入元素
24                  */
25                 arr[j] = temp;
26             }
27         }
28     }

 

157     private static void swap(int[] arr, int a, int b) {
158         int temp;
159         temp = arr[a];
160         arr[a] = arr[b];
161         arr[b] = temp;
162     }
163 }

 

posted @ 2015-07-06 20:53  凤栖梧桐镇  阅读(181)  评论(0编辑  收藏  举报