基本排序

来源:互联网 发布:python innertext 编辑:程序博客网 时间:2024/05/01 10:46

长度为N的数组升序排序

一,冒泡排序

public class BubbleSort {public void sort(int[] data){for(int p = data.length - 1 ; p > 0 ; p--){for(int i = 0 ; i < p ; i++){if(data[i] > data[i+1] ){int tmp = data[i];  data[i] = data[i+1];  data[i+1] = tmp; }}}this.display(data);}private void display(int[] data){for(int i : data){System.out.print(i+" ");}}public static void main(String[] args) {int[] data = {6, 5, 4, 3, 2, 1};BubbleSort bs = new BubbleSort();bs.sort(data);}}

比较次数:

第一次需比较N-1次,第二次需比较N-2次......,总比较次数为(N-1) + (N-2) +...+ 1 =  N*(N-1)/2

交换次数:

如果待排序数组为逆序,则需交换N*(N-1)/2次,如果待排序数组为顺序,则不需要进行交换,对于乱序数组,平均需要交换N*(N-1)/4次

时间复杂度:

N*(N-1)/2 + N*(N-1)/4,O(N*N)

 

二,选择排序

public class SelectSort {public void sort(int[] data){for(int i = 0 ; i < data.length - 1 ; i++){int flag = i;for(int j = i + 1 ; j <= data.length - 1 ; j++){if(data[j] < data[flag]){flag = j;}}int tmp = data[i];data[i] = data[flag];data[flag] = tmp;}this.display(data);}public void display(int[] data){for(int i : data){System.out.print(i + " ");}}public static void main(String[] args) {int[] data = {6, 5, 4, 3, 2, 1};SelectSort selectSort = new SelectSort();selectSort.sort(data);}}

比较次数:

第一次需比较N-1次,第二次需比较N-2次......,总比较次数为(N-1) + (N-2) +...+ 1 = N*(N-1)/2

交换次数:

如果待排序数组为逆序,则需交换N次,如果待排序数组为顺序,则不需要进行交换,则对于乱序数组,平均需要交换N/2次

时间复杂度:

N*(N-1)/2 + N/2,O(N*N),由于交换次数比冒泡排序少,因此会比冒泡排序快

 

三,插入排序:插入排序特别适合用来处理局部有序的数据

public class InsertSort {public void sort(int[] data){for(int i = 1 ; i < data.length ; i++){int tmp = data[i];int insertPoint = i;while(insertPoint > 0 && data[insertPoint-1] > tmp){data[insertPoint] = data[insertPoint-1];insertPoint -= 1;}if(insertPoint < i){data[insertPoint] = tmp;}} this.display(data);}public void display(int[] data){for(int i : data){System.out.print(i + " ");}}public static void main(String[] args) { int[] data = {1, 2, 3, 6, 5, 4};InsertSort insertSort = new InsertSort();insertSort.sort(data);           }}

比较次数:

如果带排序数组为逆序,则第一次需比较1次,第二次需比较2次......,总比较次数为1+2+...+(N-1)=N*(N-1)/2,所以在最差情况下(逆序),插入排序的比较次数和冒泡排序、选择排序是一样的,实际上每一趟排序发现插入点之前,平均只有一半的数据(待排序数组为乱序)进行了比较,所以合理的比较次数应该为:N*(N-1)/4,值得注意的是,如果待排序数据为局部有序的,则比较次数将减少很多

交换次数(需要考虑数据项移动的问题):

交换次数小于比较次数

时间复杂度:

N*(N-1)/4 + N*(N-1)/4,O(N*N)

如果数组是基本有序的,即每个数据项只需移动1次或不需要移动,那么插入排序的时间复杂度将变为O(N),这无疑是非常快的

 

四,表排序

主要是利用了有序单链表的特性(当然也可以使用二叉搜索树等等),将数组中的所有数据插入到有序链表中,它们将自动按顺序排列,然后再顺次取出链表中的所有数据,把它们放到数组中,数组便排好序了

public class SortedList {private final class Node{private int num;private Node next = null;Node(int num){this.num = num;}}private Node first = null;public void insert(int num){Node node = new Node(num);if(first == null){first = node;}else{if(node.num < first.num){node.next = first;first = node;}else{Node pre = first;Node cur = first.next;while(cur != null && (node.num > cur.num)){pre = cur;cur = cur.next;}pre.next = node;node.next = cur;}}}public int deleteFirst() throws Exception{if(first == null)throw new Exception("empty!");Node temp = first;first = first.next;return temp.num;}}
public class ListSort {public void sort(int[] data) throws Exception{SortedList sl = new SortedList();for(int num : data){sl.insert(num);}for(int i = 0 ; i< data.length ; i++){data[i] = sl.deleteFirst();}this.display(data);}public void display(int[] data){for(int i : data){System.out.print(i + " ");}}public static void main(String[] args) throws Exception{int[] data = {6, 5, 4, 3, 2, 1};  ListSort ls = new ListSort();ls.sort(data);  }}

比较次数:

将数据项插入链表平均需要比较N/2次

移动次数:

将数组数据项放入链表,再将链表数据项放回数组,总共需移动2N次

时间复杂度:

N/2 + 2N,O(N)

虽然排序速度比上面3种排序方式要快,但是需要大约2倍的内存空间,典型的空间换时间

0 0