由于学习缘故,将今日所学排序算法做以归纳总结,以备来日便宜:
插入排序:
public static void insertSort(int a[])
{
int key;
for(int j = 2;j < a.length;j++)
{
key = a[j];
//insert a[j] into the sorted sequencea[1..j-1]
int i = j - 1;
while(i > 0 && key < a[i])
{
a[i + 1] = a[i];//后面大的元素往前挪
i = i-1;
}
a[i+1] = key;//将键值插入
}
}
时间复杂度:T(n) = O(n(n - 1)/2) = O(n^2)
思想:边比较变排序,将数组分成排好序的和未排好序两段。
HeapSort
public void maxHeapyfy(int i)//维护一个大顶堆
{
if(2*i < a.length && 2*i+1 < a.length)
{
//System.out.print("@@@@@");
int leftchild = 2*i;
int rightchild = 2*i+1;
int largest;
if(leftchild <= heapsize && a[leftchild] > a[i])
largest = leftchild;
else largest = i;
//System.out.print(a[rightchild]);
if (rightchild <= heapsize && a[rightchild] > a[largest])
largest = rightchild; //找出比较大的元素
if(largest != i){//如果孩子比父亲大,就交换
int temp;
temp = a[i];
a[i] = a[largest];
a[largest] = temp;
maxHeapyfy(largest);//交换完后开始协调孩子节点作为父节点的堆
}
}
}
T(n) = O(h) = O(lgn)
public void buildHeap(){
System.out.print("建堆过程:"+"\n");
for(int i = (a.length - 2)/2;i >= 1;i--)//从下往上建堆
{
//System.out.print(a[i]);
maxHeapyfy(i);
for(int j = 1;j < a.length - 1;j++)
System.out.print(a[j]+" ");
System.out.print("***"+"\n");
}
}
T(n) = O(lgn)public void heapSort()//堆排序
{
buildHeap();
System.out.print("\n"+"建完堆后:"+"\n");
for(int j = 1;j < a.length - 1;j++)
System.out.print(a[j]+" ");
System.out.print("*_*"+"\n"+"排序过程:"+"\n");
for(int i = a.length - 2;i >= 2;i--)
{
int t;
t = a[i];//每次把第一个换到数组最后一个
a[i] = a[1];
a[1] = t;
heapsize = heapsize - 1;
for(int j = 1;j < a.length - 1;j++)
System.out.print(a[j]+" ");
System.out.print("\n");
maxHeapyfy(1);
}
}
T(n) = O(lgn) + O(nlgn) = O(lgn)
数据结构:数组,用下标来维护父子关系
HeapSort的一个应用:优先队列
<span style="font-size:12px;">public int heapMaxinum()//优先队列最大值
{
return a[1];
}
public int heapExtract()//去掉并返回堆中最大
{
if(heapsize < 1)
System.out.print("heap overflow\n");
int max = a[1];
a[1] = a[heapsize];
heapsize--;
maxHeapyfy(1);
return max;
}
public void heapIncrease(int i,int key)
{
if(a[i] > key)
System.out.print("new key is smaller than current key\n");
a[i] = key;
while(i > 1 && a[i/2] < a[i])//满足比父节点要小的性质
{
int t = a[i];
a[i] = a[i/2];
a[i/2] = t;
i = i/2;
}
}
public void maxInsert(int key)
{
heapsize = heapsize + 1;
a[heapsize] = -9999;
heapIncrease(heapsize,key);
}</span>
MergeSort:
MergeSort(a,p,r)
if p < r
q = (p+r)/2;
MergeSort(a,p,q);
MergeSort(a,q+1,r);
Merge(a,p,r); //O(n)
T(n) = 2T(n/2) + O(n)
利用主定理:a = 2;b = 2;n^(log22) = n == O(n)
case2:f(n) = O(n)*1,故k = 0;所以:T(n) = O(nlgn)
QuickSort
public static int partition(int[] a,int p,int r){//对数组a原址重排
int x = a[r];//令最后一个元素为pivot
int i = p - 1;
for(int j = p;j <= r - 1;j++)
{
if(a[j] <= x){
i++;
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
int t = a[i+1];
a[i+1] = a[r];//自此,pivot左边的元素均小于它,右边的均大于它
a[r] = t;
return i+1;
}
public static void quickSort(int[] a,int p,int r)
{
if(p < r)
{
int q = partition(a,p,r);//O(n)
quickSort(a,p,q-1);
quickSort(a,q+1,r);
}
}
pivot刚好在中间时:T(n) = 2(n/2) + O(n) ==> T(n) = O(nlgn)
pivot造成0:n-1时(也就是所有元素都相等或者已然排好序(自小到大)):T(n) = T(n-1) + T(0) + O(n) ==> T(n) = O(n^2)
algorithm | worst case | average case | best case | space cost | stable ? | implements |
---|---|---|---|---|---|---|
InsertSort | O(n^2) reverse sorted | O(n^2) | O(n) sorted | O(1) | yes | insert a[j] to sorted a[1..j-1] |
MergeSort | O(nlgn) | O(nlgn) | O(nlgn) | O(n) | yes | DC MergeSort() Merge() |
HeapSort | O(nlgn) | O(nlgn) | O(nlgn) | O(1) | no | BuliHeap() MaxHeapify() |
QuickSort | O(n^2) (0:n-1) | O(nlgn) | O(nlgn) 对半 | O(1) | no | Partition() |
BubbleSort | O(n^2) | O(n^2) | O(n) | O(1) | yes |