八大经典排序算法的代码实现

冒泡排序:

 1 //冒泡排序
 2 //时间复杂度为O(N^2),空间复杂度为O(N)
 3 public class BubbleSort {
 4     public static void bubbleSort(int[] arr) {
 5         if (arr.length == 0 || arr.length == 1) {
 6             return;
 7         } else {
 8 //            随着每轮比较的进行,都有一个大数沉到后面排好序,因此外层的循环长度应该递减
 9             for (int end = arr.length - 1; end > 0; end--) {
10                 for (int i = 0; i < end; i++) {
11                     if (arr[i] > arr[i + 1]) {
12                         swap(arr, i, i + 1);
13                     }
14                 }
15             }
16         }
17
18     }
19
20     static void swap(int[] arr, int i, int j) {
21 //        不利用第三个变量交换两变量的位置。1.a和同一个数异或运算两次得到a本身 2.异或运算满足交换律
22         arr[j] = arr[j] ^ arr[i];
23         arr[i] = arr[j] ^ arr[i];
24         arr[j] = arr[j] ^ arr[i];
25     }
26
27     public static void main(String[] args) {
28         int[] a = {2, 1, 7, 10, 3, 9, 5, 4, 6, 8};
29         bubbleSort(a);
30         for(int i:a)
31             System.out.print(i+",");
32     }
33 }

冒泡排序

插入排序:

 1 //插入排序
 2 //复杂度和数据状况有关系,如果本来数组的有序性就比较好则复杂度低
 3 public class InsertSort {
 4     public static void insertSort(int[] arr) {
 5         if (arr == null || arr.length < 2) {
 6             return;
 7         } else {
 8             for (int i = 1; i < arr.length; i++) {
 9 //如果数组的有序性比较好,如1,2,3,4,5,则arr[j + 1] < arr[j]这个条件可以使得比较提前终止,
10 //如果数组刚好是逆序的,如5,4,3,2,1,则需要从j一直比较到i=0;
11                 for (int j = i - 1; j >= 0 && arr[j + 1] < arr[j]; j--) {
12                     swap(arr, j, j + 1);
13                 }
14             }
15         }
16     }
17
18     static void swap(int[] arr, int i, int j) {
19         arr[j] = arr[j] ^ arr[i];
20         arr[i] = arr[j] ^ arr[i];
21         arr[j] = arr[j] ^ arr[i];
22     }
23
24     public static void main(String[] args) {
25         int[] a = {2, 1, 7, 10, 3, 9, 5, 4, 6, 8};
26         insertSort(a);
27         for (int i : a)
28             System.out.print(i + ",");
29     }
30 }

插入排序

选择排序:

 1 //选择排序
 2 //时间复杂度为O(N^2),空间复杂度为O(1)
 3 public class SelectionSort {
 4     public static void selectionSort(int[] arr) {
 5         if (arr == null || arr.length < 2) {
 6             return;
 7         } else {
 8 //            每轮都从未排序的数列中取出一个数,将其与后面所有未排序的数作比较,得到这些未排序数列里面的最小数,将它换到已排好序数列的后面,并扩大已排好序数列的范围。
 9             for (int i = 0; i < arr.length - 1; i++) {
10                 int minIndex = i;
11 //                i = 0作为第一个已排序列
12                 for (int j = i + 1; j < arr.length; j++) {
13                     minIndex = arr[j] < arr[minIndex] ? j : minIndex;
14                 }
15                 swap(arr, i, minIndex);
16             }
17         }
18     }
19
20     static void swap(int[] arr, int i, int j) {
21 //        此处不能用异或来完成交换,因为如果i=j, 两个相同的数异或等于0,“arr[j] = arr[j] ^ arr[i]”会将arr[i]和arr[j]同时置为0,这样就丢失了所有信息。
22 //        如果i和j不相等,但a[i]==a[j]是可以完成异或交换功能的,因为0和任何数异或等于其本身
23 //        arr[j] = arr[j] ^ arr[i];
24 //        arr[i] = arr[j] ^ arr[i];
25 //        arr[j] = arr[j] ^ arr[i];
26         int tmp = arr[i];
27         arr[i] = arr[j];
28         arr[j] = tmp;
29     }
30
31     public static void main(String[] args) {
32         int[] a = {2, 1, 7, 10, 3, 9, 5, 4, 6, 8};
33         selectionSort(a);
34         for (int i : a)
35             System.out.print(i + ",");
36     }
37 }

选择排序

归并排序:

 1 //归并排序
 2 //时间复杂度O(NlogN),空间复杂度O(N)
 3 //分治+外排的方法
 4 public class MergeSort {
 5     public static void mergeSort(int[] arr) {
 6         if (arr == null || arr.length < 2)
 7             return;
 8         else
 9             sortProcess(arr, 0, arr.length - 1);
10     }
11
12     private static void sortProcess(int[] arr, int L, int R) {
13         if (L == R)
14             return;
15         else {
16             int mid = L + ((R - L) >> 1);
17 //            根据Master公式求其时间复杂度:
18             sortProcess(arr, L, mid);//T(N/2)
19             sortProcess(arr, mid + 1, R);//T(N/2)
20             merge(arr, L, mid, R);//O(N)
21 //            根据Master公式,其时间复杂度为T(N) = 2T(N/2)+O(N) = N*logN
22         }
23     }
24
25     //融合两个有序数组,使之成为一个更大的有序数组的方法,叫做外排
26     private static void merge(int[] arr, int l, int mid, int r) {
27 //        空间复杂度O(体现在需要一个大小为数据量N的辅助数组help上)
28         int[] help = new int[r - l + 1];
29         int i = 0;
30         int p1 = l;
31         int p2 = mid + 1;
32         while (p1 <= mid && p2 <= r)
33             help[i++] = arr[p1]<=arr[p2]?arr[p1++]:arr[p2++];
34 //        两个必有且只有一个越界
35         while(p1<=mid)
36             help[i++] = arr[p1++];
37         while(p2<=r)
38             help[i++] = arr[p2++];
39
40         i = 0;
41         while(l<=r)
42             arr[l++] = help[i++];
43     }
44
45     public static void main(String[] args) {
46         int[] a = {2, 1, 7, 10, 3, 9, 5, 4, 6, 8};
47         mergeSort(a);
48         for(int i:a)
49             System.out.print(i+",");
50     }
51 }

快速排序:

 1 import java.util.Arrays;
 2
 3 //快排
 4 //时间复杂度最好为O(NlogN). 数组逆序的时候最差,时间复杂度为O(N^2),可以通过随机快排的方式使得其长期时间复杂度期望为O(N*logN)
 5 //空间复杂度最好为O(logN),数组逆序的时候最差,空间复杂度为O(N),额外空间主要是每次partition函数返回的二元数组造成的。
 6 //通过随机快排的方式使得其长期时间复杂度期望为O(logN)
 7 //所有递归函数都可以改为非递归版本,因为递归的本质行为是系统在帮我们压栈。改为非递归就是改成我们自己来压栈
 8 // 在工程上是不允许递归行为存在的,因为递归过深可能会导致系统栈爆满,系统不稳定。因此工程上的快排都是非递归版本实现的。
 9 //库函数都是高度优化过的
10 public class QuickSort {
11
12     static void quickSort(int[] arr, int L, int R) {
13         if (L < R) {
14 //            随机快排, 每次将中间随机一个数和数列最后一个元素交换位置,放置逆序数列产生差的结果
15             swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
16             int[] p = partition(arr, L, R);
17             quickSort(arr, L, p[0] - 1);
18             quickSort(arr, p[1] + 1, R);
19         }
20     }
21
22     static int[] partition(int[] arr, int L, int R) {
23         int less = L - 1;
24         int more = R;
25         int cur = L;
26 //        以arr[R]作为基准,有了随机快排,这里的arr[R]被重新洗牌
27 //        这里一次性处理了大于基准等于基准和小于基准的三种情况,速度比传统快排要快
28         while (cur < more) {
29             if (arr[cur] < arr[R]) {
30                 // cur++,因为换到cur位置上的一定是比基准arr[R]小的数,直接将其扩到less范围去,且cur指向下一位置
31                 swap(arr, ++less, cur++);
32             } else if (arr[cur] > arr[R]) {
33                 //交换到cur位置上的数大小位置,交换过去的数一定大于基准arr[R], 故more--,将其扩到more区域, 但cur位置不变
34                 swap(arr, --more, cur);
35             } else {
36                 //当前位置和基准arr[R]相等,不扩到less区域和more区域,放在相等区域
37                 cur++;
38             }
39         }
40         //最后将基准交换到more区域的下一位置
41         swap(arr, more, R);
42        // 返回相等区域下标,注意此时more位置上是交换过来的基准值,不用加1
43         return new int[]{less + 1, more};
44     }
45
46     static void swap(int[] arr, int i, int j) {
47         int tmp = arr[i];
48         arr[i] = arr[j];
49         arr[j] = tmp;
50     }
51
52     public static void main(String[] args) {
53         int a[] = {49, 38, 65, 97, 76, 13, 27, 49};
54         quickSort(a, 0, a.length - 1);
55         System.out.println(Arrays.toString(a));
56     }
57 }

快排

堆排序:

 1 import java.util.Arrays;
 2
 3 //堆排序
 4 //堆是完全二叉树
 5 //二叉树的底层可以用线性的结构来储存,也就是说可以用数组来储存一个二叉树,通过数组中下标的关系来表示这个堆。设完全二叉树的一个节点在数组中的下标为i,
 6 //则其父节点的下标应该为(i-1)/2,其左孩子节点应该是2*i+1, 其右孩子节点应该为2*i+2
 7 public class HeapSort {
 8     static void heapSort(int[] arr) {
 9         if (arr == null || arr.length < 2)
10             return;
11         else
12             for (int i = 0; i < arr.length; i++)
13                 heapInsert(arr, i);
14
15         int heapSize = arr.length;//堆的大小等于数组的长度
16         //交换堆顶和最后一个元素
17         swap(arr, 0, --heapSize);
18         while (heapSize > 0) {
19             heapify(arr, 0, heapSize);
20             swap(arr, 0, --heapSize);
21         }
22     }
23
24     static void heapInsert(int[] arr, int index) {
25         while (arr[(index - 1) / 2] < arr[index]) {//如果index=0, -1/2=0是根节点
26             swap(arr, index, (index - 1) / 2);
27             index = (index - 1) / 2;
28         }
29
30     }
31
32     //    如果堆中有某个元素变小了,将这个元素下沉以保持大根堆的过程heapify
33     static void heapify(int[] arr, int index, int heapSize) {
34         int left = index * 2 + 1;//在用数组存储的堆中,节点i的左孩子节点是2*i+1, 右节点是2*i+2;
35         //这里heapSize是最后一个元素,做堆排的时候,因为是从堆顶交换来的最大值,所以重新heapify要把它排除在外;
36         while (left < heapSize) {
37             int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
38             largest = arr[index] > arr[largest] ? index : largest;
39             if (largest == index) {
40                 break;
41             }
42             swap(arr, largest, index);
43             index = largest;
44             left = index * 2 + 1;
45         }
46     }
47
48     static void swap(int[] arr, int i, int j) {
49         int tmp = arr[i];
50         arr[i] = arr[j];
51         arr[j] = tmp;
52     }
53
54     public static void main(String[] args) {
55         int a[] = {49, 38, 65, 97, 76, 13, 27, 49};
56         heapSort(a);
57         System.out.println(Arrays.toString(a));
58     }
59 }

堆排序

希尔排序:

基数排序:

原文地址:https://www.cnblogs.com/greatLong/p/10562405.html

时间: 2024-08-30 14:52:49

八大经典排序算法的代码实现的相关文章

常见经典排序算法学习总结,附算法原理及实现代码(插入、shell、冒泡、选择、归并、快排等)

博主在学习过程中深感基础的重要,经典排序算法是数据结构与算法学习过程中重要的一环,这里对笔试面试最常涉及到的7种排序算法(包括插入排序.希尔排序.选择排序.冒泡排序.快速排序.堆排序.归并排序)进行了详解.每一种算法都有基本介绍.算法原理分析.算法代码. 转载请注明出处:http://blog.csdn.net/lsh_2013/article/details/47280135 插入排序 1)算法简介 插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法.它的工作原理是通过

经典排序算法总结(代码) .(转)

经典排序算法总结(代码) ·冒泡法 ·快速排序 ·插入排序 ·希尔(shell)排序 ·选择排序 ·堆排序 ·归并排序   附: 排序算法原理:http://zh.wikipedia.org/wiki/Category:%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95 flash演示:http://www.tyut.edu.cn/kecheng1/site01/suanfayanshi/list.asp?id=7 归并排序的具体介绍在下面的文章里: 递归算法学习---归并

十大经典排序算法的算法描述和代码实现

这里详细讲解了十大经典算法的分类,例如交换排序.插入排序.选择排序等比较类排序,以及计数排序.桶排序和基数排序的非比较类排序,分析了各种排序算法的复杂度和稳定性,还有JAVA代码的详细实现.对冒泡排序.插入排序.选择排序和堆排序等十种算法进行了详细的思想总结. 一.算法概述 1.算法分类 十种常见排序算法可以分为两大类:(1)比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn)因此也称为非线性时间比较类排序.(2)非比较类排序:不通过比较元素间的相对次序,它可以突

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

Python实现各种排序算法的代码示例总结

Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示例总结,其实Python是非常好的算法入门学习时的配套高级语言,需要的朋友可以参考下 在Python实践中,我们往往遇到排序问题,比如在对搜索结果打分的排序(没有排序就没有Google等搜索引擎的存在),当然,这样的例子数不胜数.<数据结构>也会花大量篇幅讲解排序.之前一段时间,由于需要,我复习了

经典排序算法 - 归并排序Merge sort

经典排序算法 - 归并排序Merge sort 原理,把原始数组分成若干子数组,对每个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到所有合并完,形成有序的数组 举例 无序数组[6 2 4 1 5 9] 先看一下每一个步骤下的状态,完了再看合并细节 第一步 [6 2 4 1 5 9]原始状态 第二步 [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍 第三步 [1 2 4 6] [5 9]继续两组两组合并 第四步 [1 2 4 5 6 9]合并完成,排序完成 输出结

七种经典排序算法最全攻略

经典排序算法在面试中占有很大的比重,也是基础.包括冒泡排序,插入排序,选择排序,希尔排序,归并排序,快速排序,堆排序.希望能帮助到有需要的同学.全部程序采用JAVA实现. 本篇博客所有排序实现均默认从小到大. 一.冒泡排序 BubbleSort 介绍: 冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来. 步骤: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对第0个到第n-1个数据做同样的工作.这时,最大的数就"浮"到了

经典排序算法(Java实现)

以下程序均将数据封装于DataWrap数据包装类中,如下所示: 1 //数据包装类 2 class DataWrap implements Comparable<DataWrap> 3 { 4 int data; 5 String flag; 6 public DataWrap(int data,String flag) 7 { 8 this.data = data; 9 this.flag = flag; 10 } 11 //重写compareTo方法 12 public int compa

经典排序算法 – 插入排序Insertion sort

经典排序算法 – 插入排序Insertion sort  插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕. 插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序,折半插入排序留到“查找”内容中进行.   图1演示了对4个元素进行直接插入排序的过程,共需要(a),(b),(c)三次插入. 以下代码仅供参考,欢迎指正 /// <summary> /// 插入排序 /// </summary> /// <param na