一、插入排序
直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
对于一个数组a[n]来说,第一次a[0]就构成了已拍好序的子序列,而a[2]~a[n-1]为待排序的序列。每次插入即将a[i]插入到已经排好序的子序列a[0]~a[i-1]中,如此进行n-1次插入即可。
代码实现:
public void insertSort(int[] a,int n){
int j,k,temp;
for(int i=1;i<n;i++){
//找到a[i]元素所要插入的位置,即j+1
for(j=i-1;j>=0;j--){
if(a[j]<=a[i])
break;
}
if(j!=i-1){//若j=i-1则说明a[i]就在i位置上
temp = a[i];
//将数组中j之后的元素向后移动一位
for(k=i;k>j+1;k--){
a[k] = a[k-1];
}
a[j+1] = temp;//插入元素原a[i]
}
}
}
二、堆排序
堆排序分为大顶堆和小顶堆。堆排序不适合元素较少情况。堆排序在最好最坏的情况下,其时间复杂度均为O(nlogn)。相对于快速排序来说,这是堆排序的最大优点。此外,堆排序仅需一个记录大小的供交换用的辅助存储空间。
1、构造初始堆:
先将无序数组构成二叉树。然后对此二叉树进行调整,从下标为i=n/2的节点开始考虑(因为此节点是下标最大的非叶子节点),判断此节点与其左右节点三者之间最大的值,将其交换到父节点的位置上,如此直至i=0(根节点)调整后就会得到一个顶部为最大值的堆,即为初始堆了。
2、进行堆排序 将堆顶元素输出并与堆最后一个元素交换,此时有序区的长度即为1,然后继续调整堆
直至有序区的长度为n-1时即元素也全部有序输出了,堆排序结束。
代码实现:
public class HeapClass {
//sortHeap 堆排序主方法
public void sortHeap(int[] A,int n){
if (A == null || A.length <= 1) {
return;
}
buildHeap(A, n);//建初始堆
for (int i = n-1; i >= 1; i--) {
swap(A,i,0);//将堆顶元素与堆第i个元素交换
//【重要】:从根节点开始调,未排序序列大小为i
adjustHeap(A,0,i);
}
}
//buildHeap 建立初始堆
public void buildHeap(int[] A,int n){
if (A == null || A.length <= 1) {
return;
}
for (int i = n/2; i >= 0; i--) {//从最后一个非叶子节点开始调整
adjustHeap(A, i, n);
}
}
//adjustHeap 调整堆
public void adjustHeap(int[] A,int i,int n){
int max = i;
if((2*i+1<n)&&A[2*i+1]>A[max]){
max = 2*i+1;
}
if((2*i+2<n)&&A[2*i+2]>A[max]){
max = 2*i+2;
}
if(max!=i){
swap(A,i,max);
//交换后检查子堆是否满足
adjustHeap(A,max,n);
}
}
//交换元素
public void swap(int[] A,int i,int j){
A[i] = A[i] + A[j];
A[j] = A[i] - A[j];
A[i] = A[i] - A[j];
}
public static void main(String args[]){
// int[] A = {2,6,3,1,1,9,7,4,5};
// int n = A.length;
// sortHeap(A, n);
}
}
3、归并排序
归并排序基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。为了达到合并的两个序列有序,可以将A,B组各自分成二组,依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。归并排序的效率比较高.
代码实现:
public class MergeSort {
private int[] temp;
//合并两个已经有序的序列,即数组a[]以mid为中点的左右两边
public void mergeArray(int A[], int first, int mid, int last)
{
int lFirst = first, rFirst = mid + 1;
int m = mid,n = last,k = 0;
//判断是否两个序列都有剩余时
while (lFirst <= m && rFirst <= n){
if (A[lFirst] <= A[rFirst]){
temp[k++] = A[lFirst++];
}else{
temp[k++] = A[lFirst++];
}
}
//判断是否左/右存在剩余元素,并将剩余元素直接加在temp[]数组的后面
while (lFirst <= m)
temp[k++] = A[lFirst++];
while (rFirst <= n)
temp[k++] = A[rFirst++];
//将temp存的合并后的序列赋给a[]相应位置
for (int i = 0; i < k; i++){
A[first + i] = temp[i];
}
}
//主归并类
public void mergeSort(int A[], int first, int last)
{
if (first < last)
{
int mid = (first + last)/2;
mergeSort(A, first, mid); //得到左边有序
mergeSort(A, mid + 1, last); //得到右边有序
mergeArray(A, first, mid, last); //再将二个有序数列合并
}
}
public static void main(String args[]){
// int[] A = {2,6,3,1,1,9,7,4,5};
// int n = A.length;
// mergeSort(A,0,n-1);
}
}