您的位置:首页 > 编程语言 > Java开发

java--几种简单的排序

2017-07-30 12:58 281 查看
排序是计算机内经常进行的一种操作,其目的是将一组"无序"的记录序列调整为"有序"的记录序列。这里我就用的整型数组来做案例。

冒泡排序:已知一组无序数据a[1]、a[2]、……a
,需将其按升序排列。首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。再比较a[3]与a[4],以此类推,最后比较a[n-1]与a
的值。这样处理一轮后,a
的值一定是这组数据中最大的。再对a[1]~a[n-1]以相同方法处理一轮,则a[n-1]的值一定是a[1]~a[n-1]中最大的。再对a[1]~a[n-2]以相同方法处理一轮,以此类推。共处理n-1轮后a[1]、a[2]、……a
就以升序排列了。降序排列与升序排列相类似,若a[1]小于a[2]则交换两者的值,否则不变,后面以此类推。
总的来讲,每一轮排序后最大(或最小)的数将移动到数据序列的最后,理论上总共要进行n(n-1)/2次交换。

优点:稳定;

缺点:慢,每次只能移动相邻两个数据。
public static void bubbleSort(int[] arr){
for(int i =0; i < arr.length - 1; i++){
for(int j=0; j < arr.length-1; j++){
if(arr[j] > arr[j+1]){
arr[j] = arr[j]^arr[j+1];
arr[j+1] = arr[j]^arr[j+1];
arr[j] = arr[j]^arr[j+1];
}
}
}
}选择排序:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
选择排序是不稳定的排序方法(很多教科书都说选择排序是不稳定的,但是,完全可以将其实现成稳定的排序方法)。

public static void selectSort(int[] arr){
for(int i = 0; i <arr.length -1; i++){
for(int j = i+1; j < arr.length; j++){
if(arr[j] < arr[i]){
arr[j] = arr[j]^arr[i];
arr[i] = arr[j]^arr[i];
arr[j] = arr[j]^arr[i];
}
}
}
}
 插入排序:有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数, 但要求插入后此数据序列仍然有序。
* 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,
从而得到一个新的、个数加一的有序数据,
* 插入排序由N-1趟排序组成。
* 该算法时间复杂度为O(n^2)。是稳定的排序方法。
public static void insertionSort(int[] arr){
int j;
for(int p = 1; p < arr.length; p++){
int temp = arr[p]; //保存要插入的数据
//将无序中的数和前面有序的数据相比,将比它大的数,向后移动
for(j=p; j>0 && temp <arr[j-1]; j--){
arr[j] = arr[j-1];
}
//正确的位置设置成保存的数据
arr[j] = temp;
}
}

/*
* 希尔排序:希尔排序(Shell Sort)是插入排序的一种。
* 基本思想:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。
*     所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;
*        然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
*        
* 最好时间复杂度O(n)和最坏时间复杂度0(n2)
* 希尔排序是不稳定的。
*/
public static void shellSort(int[] arr){
int j ;
for(int gap = arr.length/2; gap > 0 ; gap/=2){
for(int i = gap; i < arr.length; i++){
int temp = arr[i];
for(j = i; j>=gap && temp<arr[j-gap]; j-=gap){
arr[j] = arr[j-gap];
}
arr[j] = temp;
}
}
}快速排序:已知一组无序数据a[1]、a[2]、……a
,需将其按升序排列。首先任取数据a[x]作为基准。比较a[x]与其它数据并排序,使a[x]排在数据的第k位,并且使a[1]~a[k-1]中的每一个数据<a[x],a[k+1]~a
中的每一个数据>a[x],然后采用分治的策略分别对a[1]~a[k-1]和a[k+1]~a
两组数据进行快速排序。
public static int getMidden(int[] arr,int left,int right){
int temp = arr[left];
while(left < right){
//找到比标记值小的数据,然后交换到左边
while(left < right && temp <= arr[right]){
right--;
}
arr[left] = arr[right];
//找到比标记值大的数据,然后交换到右边
while(left < right && temp>=arr[left]){
left++;
}
arr[right] = arr[left];
}
//中间值
arr[left] = temp;
return left;
}

public static void quickSort(int[] arr,int left, int right){
if(left < right){
int mid = getMidden(arr, left, right);
quickSort(arr, left, mid-1);
quickSort(arr, mid+1, right);
}
}
归并排序:多次将两个或两个以上的有序表合并成一个新的有序表。最简单的归并是直接将两个有序的子表合并成一个有序的表。
public static void mergeSort(int[] arr){
int[] tempArray = new int[arr.length];
mergeSort(arr,tempArray,0,arr.length-1);
}
private static void mergeSort(int[] arr, int[] tempArray,int left,
int right){
if(left < right){
int center = (left+right)/2;
mergeSort(arr,tempArray,left,center);
mergeSort(arr,tempArray,center+1,right);
merge(arr,tempArray,left,center+1,right);
}
}
private static void merge(int[] arr, int[] tempArray,int leftPos,
int rightPos,int rightEnd){
int leftEnd = rightPos-1;
int tempPos = leftPos;
int numElements = rightEnd-leftPos+1;
while(leftPos<=leftEnd && rightPos<=rightEnd){
if(arr[leftPos] < arr[rightPos]){
tempArray[tempPos++] = arr[leftPos++];
}else{
tempArray[tempPos++] = arr[rightPos++];
}
}

while(leftPos <= leftEnd){
tempArray[tempPos++] = arr[leftPos++];
}
while(rightPos <= rightEnd){
tempArray[tempPos++] = arr[rightPos++];
}
for(int i = 0; i < numElements; i++,rightEnd--){
arr[rightEnd] = tempArray[rightEnd];
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: