目录
长度为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 = =
交换次数:
如果待排序数组为逆序,交换次数等于比较次数
时间复杂度:
+
= O(
)
选择排序
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-1次
时间复杂度:
+ N -1 = O(
),由于交换次数比冒泡排序少,因此会比冒泡排序快
插入排序
插入排序特别适合用来处理局部有序的数据
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倍的内存空间,典型的空间换时间