基础排序算法(Java实现)

来源:互联网 发布:网络主播毒药黄播 编辑:程序博客网 时间:2024/06/07 19:34

1.插入排序

将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止

/** * 插入排序,复杂度O(n^2) * @author Qing * */public class Insert {//打印数组public static void print(int[] a){int n = a.length;System.out.println(" ");for(int i = 0; i < n; i ++){System.out.print(a[i] + " ");}System.out.println(" ");}//不使用递归的插入排序public static int[] InsertionSort(int[] a, int n){int temp_a = 0;for(int i = 1; i < n; i ++){temp_a = a[i];int j = i - 1;// 与前面的数字进行逐一比较和移位while(j >= 0 && temp_a < a[j]){a[j + 1] = a[j];j = j - 1;}a[j + 1] = temp_a;//print(a);}return a;}//递归插入排序public static int[] Recursive_InsertionSort(int[] a, int q){if(q >1){Recursive_InsertionSort(a,q-1);Insert_List(a,q-1);}return a;}public static void Insert_List(int[] a, int q){int temp_a = a[q];int j = q-1;while(j >= 0 && temp_a < a[j]){a[j + 1] = a[j];a[j] = temp_a;j = j - 1;}print(a);}public static void main(String[] args){int[] a = {10,1,5,10,4,9,5,41,21,13,4,8,11};System.out.print("the original list: ");print(a);//System.out.print("after insert sort: ");//int[] b = InsertionSort(a,a.length);//print(b);System.out.print("after recursive insert sort: ");int[] c = Recursive_InsertionSort(a,a.length-1);print(c);}}

2、归并排序

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

/** * 归并排序,复杂度O(nlogn) * @author Administrator * */public class Merge {public static void print(int[] a){int n = a.length;System.out.println(" ");for(int i = 0; i < n; i ++){System.out.print(a[i] + " ");}System.out.println(" ");}public static int[] MergeSort(int[] a){int low = 0;int high = a.length -1;int[] d = a;if(low < high){int divide = a.length/2;int[] b = new int[divide - low ];int[] c = new int[high - divide +1];//将a分为两个部分b和cfor(int i = low; i <= high; i ++){if(i < divide){b[i] = a[i];}else{c[i - divide] = a[i];}}//分别对b和c进行归并排序b = MergeSort(b);c = MergeSort(c);//将bc合并为dd = Merge(b,c);print(d);return d;}return d;}//将b和c进行合并public static int[] Merge(int[] b, int[] c){int[] d = new int[b.length + c.length];int b_i = 0;int c_i = 0;int i = 0;while(b_i < b.length && c_i < c.length){if(b[b_i] < c[c_i]){d[i] = b[b_i];i ++;b_i ++;}else{d[i] = c[c_i];i ++;c_i ++;}}while(b_i < b.length){d[i] = b[b_i];i++;b_i ++;}while(c_i < c.length){d[i] = c[c_i];i ++;c_i ++;}return d;}public static void main(String[] args){int[] a = {10,1,5,10,4,9,5,41,21,13,4,8,11};System.out.print("the original list: ");print(a);System.out.println("");System.out.println("after merge sort: ");int[] d = new int[a.length];d = MergeSort(a);print(d);}} 

3.快速排序

1)选择一个基准元素,通常选择第一个元素或者最后一个元素,

2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。

3)将基准元素放置在两部分中间。

4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。


/** * 快速排序 O(nlgn) * @author Qing * */public class Quick {public static void print(int[] a){int n = a.length;System.out.println("");for(int i = 0; i < n; i ++){System.out.print(a[i] + " ");}}//将表根据基准元素分为大于基准数和小于基准数public static int partition(int[] a, int low, int high){int privokey = a[low]; //基准元素int temp = 0;int j = low;int i = 0;for(i=low +1; i<=high; i++){if(a[i] < privokey){j++;temp = a[i];//将比基准元素小的元素换到前面a[i] = a[j];a[j] = temp;}}temp = a[j];//将基准元素换到中间a[j] = a[low];a[low] = temp;print(a);return j;}public static void quickSort(int[] a, int low, int high){if(low < high){int privokey = partition(a,low,high);quickSort(a,low,privokey - 1);quickSort(a,privokey + 1,high);}}public static void main(String[] args){int[] a = {10,1,5,10,4,9,5,41,21,13,4,8,11};System.out.print("the original list: ");print(a);System.out.println("");System.out.print("after quick sort: ");quickSort(a,0,a.length-1);print(a);}}

4.冒泡排序

在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

/** * 冒泡排序,让大数下沉,小数上冒,复杂度O(n^2) * @author Qing * */public class Bubble {public static void print(int[] a){int n = a.length;System.out.println("");for(int i = 0; i < n; i ++){System.out.print(a[i] + " ");}System.out.println("");}public static int[] BubbleSort(int[] a){int n = a.length;for(int i = 0; i < n-1; i ++){for(int j = 0; j < n - i - 1; j++){if(a[j] > a[j + 1]){int temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;}}print(a);}return a;}//改进后加标志的冒泡排序,flag用于记录每趟排序中最后一次进行交换的位置。下一次只需要扫描到flag位即可。public static int[] Bubble_flag(int[] a){int n = a.length;int i = n -1;//最后位置while(i > 0){int flag = 0;//开始时无交换for(int j = 0; j < i; j++){if(a[j] > a[j + 1]){flag = j;//记录交换的位置int temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;}}i = flag;print(a);}return a;}public static void main(String[] args){int[] a = {10,1,5,10,4,9,5,41,21,13,4,8,11};System.out.print("the original list: ");print(a);System.out.print("after bubble sort: ");int[] b = BubbleSort(a);print(b);//System.out.print("after flag bubble sort: ");//int[] c = Bubble_flag(a);//print(c);}}


5.堆排序



若以一维数组存储一个堆,则堆对应一棵完全二叉树,且所有非叶结点的值均不大于(或不小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的。如:

(a)大顶堆序列:(96, 83,27,38,11,09)

  (b)  小顶堆序列:(12,36,24,85,47,30,53,91)



初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n 个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次小(或次大)的元素。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。称这个过程为堆排序

因此,实现堆排序需解决两个问题:
1. 如何将n 个待排序的数建成堆;
2. 输出堆顶元素后,怎样调整剩余n-1 个元素,使其成为一个新堆。


首先讨论第二个问题:输出堆顶元素后,对剩余n-1元素重新建成堆的调整过程。

调整小顶堆的方法:

1)设有m 个元素的堆,输出堆顶元素后,剩下m-1 个元素。将堆底元素送入堆顶((最后一个元素与堆顶进行交换),堆被破坏,其原因仅是根结点不满足堆的性质。

2)将根结点与左、右子树中较小元素的进行交换。

3)若与左子树交换:如果左子树堆被破坏,即左子树的根结点不满足堆的性质,则重复方法 (2).

4)若与右子树交换,如果右子树堆被破坏,即右子树的根结点不满足堆的性质。则重复方法 (2).

5)继续对不满足堆性质的子树进行上述交换操作,直到叶子结点,堆被建成。

称这个自根结点到叶子结点的调整过程为筛选。如图:



对n 个元素初始建堆的过程。
建堆方法:对初始序列建堆的过程,就是一个反复进行筛选的过程。

1)n 个结点的完全二叉树,则最后一个结点是第个结点的子树。

2)筛选从第个结点为根的子树开始,该子树成为堆。

3)之后向前依次对各结点为根的子树进行筛选,使之成为堆,直到根结点。

/** * 堆排序 O(nlogn) * @author Qing * */public class Heap {/* * 初始堆处理 */public static void BuildingHeap(int[] a){int n = a.length;//最后一个有子节点的位置:i = (length -1)/2,根据堆得定义for(int i = (n - 1)/2; i >=0; i--){HeapAdjust(a,i,n);}}/* * 将节点i及其子节点的位置进行排序 */public static void HeapAdjust(int[] a, int i, int length){int tmp = a[i];int child = 2*i+1;//左孩子位置while(child < length){//找到大的孩子节点if(child+1 < length &&a[child] < a[child +1]){child ++;}//将大的孩子与父节点交换,保证父节点大于任何一个孩子if(a[i] < a[child]){a[i] = a[child];i = child;child = 2*i +1;}else{break;}a[i] = tmp;}print(a);}//堆排序public static void HeapSort(int[] a){int length = a.length;BuildingHeap(a);//初始化System.out.println("heap built");for(int i = length - 1; i > 0; i--){//交换堆顶元素和堆中最后一个元素int tmp = a[i];a[i] = a[0];a[0] = tmp;//每次交换完之后再次调整HeapAdjust(a,0,i);System.out.println("heap adjust");}}public static void print(int[] a){int length = a.length;for(int i = 0; i < length; i ++){System.out.print(a[i] + " ");}System.out.println("");}public static void main(String[] args){int[] a = {10,1,5,10,4,5,11,87,54,36};System.out.print("the original list: ");print(a);HeapSort(a);print(a);}}


0 0
原创粉丝点击