冒泡排序
冒泡排序的基本思想是: 通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。
1、比较两个相邻的数,如果前面的数大于后面的数,则将这两个数交换位置。第一次遍历后,最大的数会被放到数组的最后位置,即array[length - 1]。
2、第二次遍历时跳过最后一个元素,因为该元素通过第一次遍历已经确定是最大值。
3、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
优点:冒泡排序算法简单,稳定可靠。
缺点:当数据量庞大并且乱序严重时,比较次数多,排序效率低。
public class Test {
public static void main(String[] args) {
int[] nums = {1,2,31,4,5,50};
bubbleSort(nums);
System.out.println(Arrays.toString(nums));
}
private static void bubbleSort(int[] nums){
for(int i = 0;i<nums.length-1;i++){
for(int j = 0;j< nums.length-i-1;j++){
if(nums[j]>nums[j+1]){
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = nums[j];
}
}
}
}
}
快速排序
快速排序算法通过多次比较和交换来实现排序,其排序流程如下:(1) 首先设定一个分界值,通过该分界值将数组分成左右两部分。(2) 将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。(3) 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。(4) 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。快速排序的优点是平均性能好,缺点是不稳定,如果初始序列是有序的,那么时间复杂度为O(n^2)。
public class Test {
public static void main(String[] args) {
int[] nums = {1,2,31,4,5,50};
sort(nums,0,nums.length-1);
System.out.println(Arrays.toString(nums));
}
public static void quickSort(int[] arr,int low,int high) {
int i, j, temp, t;
if (low > high) {
return;
}
i = low;
j = high;
//temp就是基准位
temp = arr[low];
while (i < j) {
//先看右边,依次往左递减
while (temp <= arr[j] && i < j) {
j--;
}
//再看左边,依次往右递增
while (temp >= arr[i] && i < j) {
i++;
}
//如果满足条件则交换
if (i < j) {
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
//最后将基准为与i和j相等位置的数字交换
arr[low] = arr[i];
arr[i] = temp;
//递归调用左半数组
quickSort(arr, low, j - 1);
//递归调用右半数组
quickSort(arr, j + 1, high);
}
}
归并排序
归并排序是一种基于分治思想的排序算法,它将待排序的数组分成两部分,分别对这两部分递归地进行排序,最后将两个有序子数组合并成一个有序数组。它的时间复杂度为 O(nlogn)。
归并排序的基本思路是将待排序的数组分成两个部分,分别对这两部分进行排序,然后将排好序的两部分合并成一个有序数组。这个过程可以用递归来实现。具体的实现步骤如下:
分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。
合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止。
合并的过程中,需要用到一个辅助数组来暂存合并后的有序数组。具体来说,假设待合并的两个有序数组分别为 A 和 B,它们的长度分别为 n 和 m,合并后的有序数组为 C,那么合并的过程可以按如下步骤进行:
定义三个指针 i、j 和 k,分别指向数组 A、B 和 C 的起始位置。
比较 A[i] 和 B[j] 的大小,将小的元素放入 C[k] 中,并将对应指针向后移动一位。
重复步骤 2,直到其中一个数组的元素全部放入 C 中。
将另一个数组中剩余的元素放入 C 中。
归并排序的优点是稳定性好,即对于相等的元素,在排序前后它们的相对位置不会改变。缺点是需要额外的空间来存储辅助数组。
public class Test {
public static void main(String[] args) {
int[] nums = {1,2,31,4,5,50};
mergesort(nums,0, nums.length-1);
System.out.println(Arrays.toString(nums));
}
private static void mergesort(int[] nums,int left,int right){
if(left>=right){
return;
}
int mid = left+right>>1;
mergesort(nums,left,mid);
mergesort(nums,mid+1,right);
int[] temp = new int[right-left +1];
int k = 0,i = left,j = mid+1;
while (i<=mid&&j<=right){
if(nums[i]<nums[j]) temp[k++] = nums[i++];
else temp[k++] = nums[j++];
}
while(i<=mid) temp[k++] = nums[i++];
while (j<=right) temp[k++] = nums[j++];
for(i = left,j = 0;i<=right;i++,j++)
nums[i] = temp[j];
}
}
各种排序算法的复杂度比较