如有不足,还望指正,不胜感激,共同学习。
目录
排序
所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。排序算法,就是如何使得记录按照要求排列的方法。排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面。一个优秀的算法可以节省大量的资源。在各个领域中考虑到数据的各种限制和规范,要得到一个符合实际的优秀算法,得经过大量的推理和分析。
常见排序算法
冒泡排序、插入排序、选择排序、希尔排序、归并排序、快速排序
冒泡排序
冒泡排序算法是把较小的元素往前调或者把较大的元素往后调。这种方法主要是通过对相邻两个元素进行大小的比较,根据比较结果和算法规则对该二元素的位置进行交换,这样逐个依次进行比较和交换,就能达到排序目的。冒泡排序的基本思想是,首先将第1个和第2个记录的关键字比较大小,如果是逆序的,就将这两个记录进行交换,再对第2个和第3个记录的关键字进行比较,依次类推,重复进行上述计算,直至完成第(n一1)个和第n个记录的关键字之间的比较,此后,再按照上述过程进行第2次、第3次排序,直至整个序列有序为止。排序过程中要特别注意的是,当相邻两个元素大小一致时,这一步操作就不需要交换位置,因此也说明冒泡排序是一种严格的稳定排序算法,它不改变序列中相同元素之间的相对位置关系。
代码实现:
public static void main (String[] args){
int arr[] = {9,2,6,8,4};
//冒泡排序
for(int i =0;i<arr.length;i++){//外层循环,遍历次数
for(int j = i;j<arr.length-i-1;j++){
//内层循环,升序(如果前一个比后一个大,则交换,否则不变),降序反之
//循环一次,固定一个值
if(arr[j]>arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
//过程
2,6,8,4,9
2,6,4,8,9
2,4,6,8,9
2,4,6,8,9
2,4,6,8,9
}
插入排序
插入排序算法是基于某序列已经有序排列的情况下,通过一次插入一个元素的方式按照原有排序方式增加元素。这种比较是从该有序序列的最末端开始执行,即要插入序列中的元素最先和有序序列中最大的元素比较,若其大于该最大元素,则可直接插入最大元素的后面即可,否则再向前一位比较查找直至找到应该插入的位置为止。插入排序的基本思想是,每次将1个待排序的记录按其关键字大小插入到前面已经排好序的子序列中,寻找最适当的位置,直至全部记录插入完毕。执行过程中,若遇到和插入元素相等的位置,则将要插人的元素放在该相等元素的后面,因此插入该元素后并未改变原序列的前后顺序。我们认为插入排序也是一种稳定的排序方法。插入排序分直接插入排序、折半插入排序和希尔排序3类。
代码实现:
public static void main (String[] args){
//插入排序
int arr[] = {7,2,5,6,9};
for(int i = 1 ;i<arr.length; i++){//外层循环
for(int j = i;j>0; j--){//内存循环,与前面排好序的数据比较,如果后面的数据小于前面的则交换
if(arr[j]<arr[j-1]){
int temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}else{//如果不小于,说明插入完毕,退出内层循环
break;
}
}
}
}
//过程
2,7,5,6,9
2,5,7,6,9
2,5,6,7,9
选择排序
选择排序算法的基本思路是为每一个位置选择当前最小的元素。选择排序的基本思想是,基于直接选择排序和堆排序这两种基本的简单排序方法。首先从第1个位置开始对全部元素进行选择,选出全部元素中最小的给该位置,再对第2个位置进行选择,在剩余元素中选择最小的给该位置即可;以此类推,重复进行“最小元素”的选择,直至完成第(n-1)个位置的元素选择,则第n个位置就只剩唯一的最大元素,此时不需再进行选择。使用这种排序时,要注意其中一个不同于冒泡法的细节。举例说明:序列58539.我们知道第一遍选择第1个元素“5”会和元素“3”交换,那么原序列中的两个相同元素“5”之间的前后相对顺序就发生了改变。因此,我们说选择排序不是稳定的排序算法,它在计算过程中会破坏稳定性。
代码实现:
public static void main(String[] args){
//选择排序
int arr[] = {6,5,3,2,4};
for(int i = 0 ;i < arr.length; i++){
//默认第一个为最小值
int min = arr[i];
int index = i;
for(int j = i+1; j< arr.length; j++){
if(arr[j]<min){
min = arr[j];
index = j;
}
}
int temp =arr[i];
arr[i] = min;
arr[index] = temp;
System.out.println(Arrays.toString(arr));
}
}
//过程
[2, 5, 3, 6, 4]
[2, 3, 5, 6, 4]
[2, 3, 4, 6, 5]
[2, 3, 4, 5, 6]
[2, 3, 4, 5, 6]
希尔排序
基本上和插入排序一样的道理,不一样的地方在于,每次循环的步长,通过减半的方式来实现。基本原理和插入排序类似,不一样的地方在于。通过间隔多个数据来进行插入排序。
代码实现:
public static void main (String[] args){
//希尔排序
int arr[] = {7,9,5,1,3};
for(int i = arr.length/2;i>0;i/=2){
for(int j = i;j<arr.length;j++){
for(int k = j;k>0&&k-i>=0;k-=i){
if(arr[k]<arr[k-i]){
int temp = arr[k-i];
arr[k-i] = arr[k];
arr[k] = temp;
System.out.println(Arrays.toString(arr));
}else{
break;
}
}
}
}
}
//过程
[5, 9, 7, 1, 3]
[5, 1, 7, 9, 3]
[5, 1, 3, 9, 7]
[3, 1, 5, 9, 7]
[1, 3, 5, 9, 7]
[1, 3, 5, 7, 9]
归并排序
将列表按照对等的方式进行拆分,拆分小最小快的时候,在将最小块按照原来的拆分,进行合并,合并的时候,通过左右两块的左边开始比较大小。小的数据放入新的块中。简单一点就是先对半拆成最小单位,然后将两半数据合并成一个有序的列表。
代码实现:
public static void main(String[] args){
//归并排序
int arr[] = {7, 5, 3, 2, 4, 1,6};
int start = 0 ;
int end = arr.length-1;
mergeSort(arr,start,end);
}
public static void mergeSort(int[] arr, int start, int end) {
//判断拆分的不为最小单位
if (end - start > 0) {
//再一次拆分,知道拆成一个一个的数据
mergeSort(arr, start, (start + end) / 2);
mergeSort(arr, (start + end) / 2 + 1, end);
//记录开始/结束位置
int left = start;
int right = (start + end) / 2 + 1;
//记录每个小单位的排序结果
int index = 0;
int[] result = new int[end - start + 1];
//如果查分后的两块数据,都还存在
while (left <= (start + end) / 2 && right <= end) {
//比较两块数据的大小,然后赋值,并且移动下标
if (arr[left] <= arr[right]) {
result[index] = arr[left];
left++;
} else {
result[index] = arr[right];
right++;
}
//移动单位记录的下标
index++;
}
//当某一块数据不存在了时
while (left <= (start + end) / 2 || right <= end) {
//直接赋值到记录下标
if (left <= (start + end) / 2) {
result[index] = arr[left];
left++;
} else {
result[index] = arr[right];
right++;
}
index++;
}
//最后将新的数据赋值给原来的列表,并且是对应分块后的下标。
for (int i = start; i <= end; i++) {
arr[i] = result[i - start];
System.out.println(Arrays.toString(arr));
}
}
}
//过程
[5, 5, 3, 2, 4, 1, 6]
[5, 7, 3, 2, 4, 1, 6]
[5, 7, 2, 2, 4, 1, 6]
[5, 7, 2, 3, 4, 1, 6]
[2, 7, 2, 3, 4, 1, 6]
[2, 3, 2, 3, 4, 1, 6]
[2, 3, 5, 3, 4, 1, 6]
[2, 3, 5, 7, 4, 1, 6]
[2, 3, 5, 7, 1, 1, 6]
[2, 3, 5, 7, 1, 4, 6]
[2, 3, 5, 7, 1, 4, 6]
[2, 3, 5, 7, 1, 4, 6]
[2, 3, 5, 7, 1, 4, 6]
[1, 3, 5, 7, 1, 4, 6]
[1, 2, 5, 7, 1, 4, 6]
[1, 2, 3, 7, 1, 4, 6]
[1, 2, 3, 4, 1, 4, 6]
[1, 2, 3, 4, 5, 4, 6]
[1, 2, 3, 4, 5, 6, 6]
[1, 2, 3, 4, 5, 6, 7]
快速排序
快速排序的基本思想是:通过一趟排序算法把所需要排序的序列的元素分割成两大块,其中,一部分的元素都要小于或等于另外一部分的序列元素,然后仍根据该种方法对划分后的这两块序列的元素分别再次实行快速排序算法,排序实现的整个过程可以是递归的来进行调用,最终能够实现将所需排序的无序序列元素变为一个有序的序列。
代码实现:
public static void main(String[] args){
int arr[] = {7, 5, 3, 2, 4, 1, 8, 9, 6};
//快速排序
int low = 0;
int high = arr.length - 1;
quickSort(arr, low, high);
}
public static void quickSort(int[] arr, int low, int high) {
//如果指针在同一位置(只有一个数据时),退出
if (high - low < 1) {
return;
}
//标记,从高指针开始,还是低指针(默认高指针)
boolean flag = true;
//记录指针的其实位置
int start = low;
int end = high;
//默认中间值为低指针的第一个值
int midValue = arr[low];
while (true) {
//高指针移动
if (flag) {
//如果列表右方的数据大于中间值,则向左移动
if (arr[high] > midValue) {
high--;
} else if (arr[high] < midValue) {
//如果小于,则覆盖最开始的低指针值,并且移动低指针,标志位改成从低指针开始移动
arr[low] = arr[high];
low++;
flag = false;
}
} else {
//如果低指针数据小于中间值,则低指针向右移动
if (arr[low] < midValue) {
low++;
} else if (arr[low] > midValue) {
//如果低指针的值大于中间值,则覆盖高指针停留时的数据,并向左移动高指针。切换为高指针移动
arr[high] = arr[low];
high--;
flag = true;
}
}
//当两个指针的位置相同时,则找到了中间值的位置,并退出循环
if (low == high) {
arr[low] = midValue;
System.out.println(Arrays.toString(arr));
break;
}
}
//然后出现有,中间值左边的小于中间值。右边的大于中间值。
//然后在对左右两边的列表在进行快速排序
quickSort(arr, start, low -1);
quickSort(arr, low + 1, end);
}
//过程
[6, 5, 3, 2, 4, 1, 7, 9, 8]
[1, 5, 3, 2, 4, 6, 7, 9, 8]
[1, 5, 3, 2, 4, 6, 7, 9, 8]
[1, 4, 3, 2, 5, 6, 7, 9, 8]
[1, 2, 3, 4, 5, 6, 7, 9, 8]
[1, 2, 3, 4, 5, 6, 7, 9, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
常见的排序就先整理到这儿。。