经典的排序算法java实现版

  1 /**
  2  * 
  3  * @author yuzhiping
  4  * @version 1.0
  5  * 功能说明:计算机领域经典的算法
  6  *
  7  */
  8 public class sortAlgorithm<T extends Comparable<T>> {
  9     
 10     //交换索引i和索引j的值
 11     private void swap(T [] data ,int i,int j){
 12         T tmp;
 13         tmp=data[i];
 14         data[i]=data[j];
 15         data[j]=tmp;
 16     }
 17     
 18     
 19     //-----堆排序 时间复杂度O(nlogn)-----
 20     
 21     public void heapSort(T [] data){
 22         int arrayLength=data.length;
 23         //循环件堆
 24         for(int i=0;i<arrayLength-1;i++){
 25             // 建堆
 26             builMaxdHeap(data, arrayLength - 1 - i);
 27             // 交换堆顶和最后一个元素
 28             swap(data, 0, arrayLength - 1 - i);
 29 
 30         }
 31     }
 32     
 33     // 对data数组从0到lastIndex建大顶堆
 34     private void builMaxdHeap(T[] data, int lastIndex) {
 35         // 从lastIndex处节点(最后一个节点)的父节点开始
 36         for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
 37             // k保存当前正在判断的节点
 38             int k = i;
 39             // 如果当前k节点的子节点存在
 40             while (k * 2 + 1 <= lastIndex) {
 41                 // k节点的左子节点的索引
 42                 int biggerIndex = 2 * k + 1;
 43                 // 如果biggerIndex小于lastIndex,即biggerIndex + 1
 44                 // 代表的k节点的右子节点存在
 45                 if (biggerIndex < lastIndex) {
 46                     // 如果右子节点的值较大
 47                     if (data[biggerIndex].compareTo(data[biggerIndex + 1]) < 0) {
 48                         // biggerIndex总是记录较大子节点的索引
 49                         biggerIndex++;
 50                     }
 51                 }
 52                 // 如果k节点的值小于其较大子节点的值
 53                 if (data[k].compareTo(data[biggerIndex]) < 0) {
 54                     // 交换它们
 55                     swap(data, k, biggerIndex);
 56                     // 将biggerIndex赋给k,开始while循环的下一次循环,
 57                     // 重新保证k节点的值大于其左、右子节点的值。
 58                     k = biggerIndex;
 59                 } else {
 60                     break;
 61                 }
 62             }
 63         }
 64     }
 65      
 66     //-----冒泡排序法 时间复杂度O(n^2)-----
 67     public void bubbleSort(T[] data){
 68         int i,j;
 69         for(i=0;i<data.length-1;i++){
 70             for(j=0;j<data.length-i-1;j++){
 71                 if(data[j].compareTo(data[j+1]) > 0){
 72                     swap(data,j+1,j);
 73                 }
 74             }
 75         }
 76     }
 77      
 78     //-----选择排序法 时间复杂度O(n^2)-----
 79     public void selectSort(T[] data){
 80         int i,j;    
 81          
 82         for(i=0;i<data.length-1;i++){
 83             for(j=i+1;j<data.length;j++){
 84                 if (data[i].compareTo(data[j]) > 0){
 85                     swap(data,i,j);
 86                 }
 87             }
 88         }
 89     }
 90      
 91     //-----快速排序法  时间复杂度为O(log2n)-----
 92     public void quickSort(T[] data){
 93         subQuickSort(data,0,data.length-1);
 94     }
 95      
 96     private void subQuickSort(T[] data,int start,int end){
 97         if( start < end ){
 98             //以第一个元素作为分界值
 99             T base = data[start];
100             //i从左边开始搜索大于分界值元素的索引
101             int i = start;
102             //j从右边开始搜索小于分界值元素的索引
103             int j = end + 1;
104             while(true){
105                 //左边跳过比base小的元素
106                 while(i < end && data[++i].compareTo(base) <= 0);
107                 //右边跳过比base大的元素
108                 while(j > start && data[--j].compareTo(base) >= 0);
109                  
110                 if(j > i){
111                     swap(data,i,j);
112                 }else{
113                     break;
114                 }
115             }
116             //将分界值还原
117             swap(data,start,j);
118              
119             //递归左边序列
120             subQuickSort(data,start,j-1);
121             //递归右边序列
122             subQuickSort(data,j+1,end);
123         }
124     }
125      
126     //-----插入排序法 时间复杂度O(n^2)-----
127     public void insertSort(T[] data){
128         int arrayLength = data.length;
129          
130         for(int i=1;i<arrayLength;i++){
131             //当整体后移时保证data[i]的值不会丢失
132             T tmp = data[i];
133             //i索引处的值已经比前面所有值都大,表明已经有序,无需插入
134             //i-1处索引之前的数值已经有序,i-1处索引处元素的值也是最大值
135             if(data[i].compareTo(data[i-1]) < 0){
136                 int j = i-1;
137                 //整体后移一个
138                 while(j>=0 && data[j].compareTo(tmp) > 0){
139                     data[j+1] = data[j];
140                     j--;
141                 }
142             data[j+1] = tmp;
143             }
144         }
145     }
146      
147     //-----折半插入排序法 时间复杂度-----
148     public void binaryInsertSort(T[] data) {
149         int arrayLength = data.length;
150  
151         for (int i = 1; i < arrayLength; i++) {
152             if (data[i - 1].compareTo(data[i]) > 0) {
153                 // 缓存i处的元素值
154                 T tmp = data[i];
155  
156                 // 记录搜索范围的左边界
157                 int low = 0;
158                 // 记录搜索范围的右边界
159                 int high = i - 1;
160  
161                 while (high >= low) {
162                     // 记录中间位置
163                     int mid = (high + low) / 2;
164                     // 比较中间位置数据和i处数据大小,以缩小搜索范围
165  
166                     if (tmp.compareTo(data[mid]) > 0) {
167                         low = mid + 1;
168                     } else {
169                         high = mid - 1;
170                     }
171                 }
172                 // 将low~i处数据整体向后移动1位
173                 for (int j = i; j > low; j--) {
174                     data[j] = data[j - 1];
175                 }
176                 data[low] = tmp;
177  
178             }
179         }
180     }
181      
182     //-----希尔排序法 时间复杂度O(nlogn)O(n^2)具体看h的值-----
183     public void shellSort(T[] data){
184         int arrayLength = data.length;
185         //h保存可变增量
186          
187         int h = 1;
188         while(h<=arrayLength/3){
189             h = h * 3 + 1;
190         }
191          
192         while(h > 0){
193             //System.out.println(Arrays.toString( data )+"h="+h);
194              
195             for(int i=h;i<arrayLength;i++){
196                 //当整体后移时,保证data[i]的值不丢失
197                 T tmp = data[i];
198                 //i索引处的值已经比前面所有的值大
199                 //(i-1索引之前的值已经有序的,i-1索引处元素的值就是最大值)
200                 if(data[i].compareTo(data[i-h]) < 0){
201                     int j = i-h;
202                     //整体后移一格
203                     while(j>=0 && data[j].compareTo(tmp) > 0){
204                         data[j+h] = data[j];
205                         j-=h;
206                     }
207                      
208                     //最后将tmp值插入合适的位置
209                     data[j+h] = tmp;
210                 }
211             }
212             h = (h-1)/3;
213         }
214          
215     }
216      
217     //-----归并排序法 时间复杂度为O(nlog2n)-----
218     public void mergeSort(T[] data){
219         subMergeSort(data,0,data.length-1);
220     }
221      
222     private void subMergeSort(T[] data,int left,int right){
223         if(right > left){
224             //找出中间索引
225             //System.out.println(  Arrays.toString(data) );
226             int center = (left + right)/2;
227             //对左边数组进行递归
228             subMergeSort(data,left,center);
229             //对右边数组进行递归
230             subMergeSort(data,center+1,right);
231             //合并
232             merge(data,left,center,right);
233         }
234     }
235      
236     @SuppressWarnings("unchecked")
237     private void merge(T[] data, int left, int center, int right) {
238         Object[] tmpArr = new Object[data.length];
239         int mid = center + 1;
240         // third记录中间处索引
241         int third = left;
242         int tmp = left;
243  
244         while (left <= center && mid <= right) {
245             // 从两个数组中取出最小的放入中间数组
246             if (data[left].compareTo(data[mid]) <= 0) {
247                 tmpArr[third++] = data[left++];
248             } else {
249                 tmpArr[third++] = data[mid++];
250             }
251         }
252          
253         // 剩余部分依次放入中间数组
254         while (mid <= right) {
255             tmpArr[third++] = data[mid++];
256         }
257         while (left <= center) {
258             tmpArr[third++] = data[left++];
259         }
260          
261         // 将中间数组的内容复制拷回原数组
262         // (原left~right范围内德内容被复制回原数组)
263         while (tmp <= right) {
264             data[tmp] = (T) tmpArr[tmp++];
265         }
266     }
267      
268 
269 
270     public static void main(String[] args) {
271         // TODO Auto-generated method stub
272 
273     }
274 
275 }

 

posted @ 2015-05-03 22:41  余家小子  阅读(693)  评论(0编辑  收藏  举报