排序算法总结
插入算法
- 思想:每次选择一个元素k,将其插入到前面已经有序的部分数组里。A[0...j]已经有序,从n处向前扫描:如果K比A[i]小,说明要继续往前寻找插入的位置,并且将A[i]往后移动;如果K比A[i]大说明应该插入A[i]后面处,然后break,将A[I+1]赋值为K值。
/*
插入排序伪代码:
insertSort(A,n)
for j(1,n)
do:key <= A[j],i <= j-1
while(i>=0 and A[i]>key
do:A[i+1] <=A[i],i=i-1
A[i+1]=key
复杂度:最坏0(n^2),平均:o(n^2)。最好o(n),稳定,空间复杂度o(1)
*/
public static void InsertSort(int A[],int n) {
for(int j=1;j<n;j++) {
int key=A[j],i;
for(i=j-1;i>=0;i-- ) {
if(A[i]>key)
A[i+1]=A[i];
else
break;
}
A[i+1]=key;
}
}
希尔排序
- 思想:希尔排序也是一种插入排序,采用分组直接插入方式,可以降低复杂度,最坏情况:o(logn),平均复杂度:o(logn);不稳定
- 步骤:选取第一个增量d1,把表分成d1个组,把数组里下表距离为d1的分为一组,用插入排序算法排好序,使得每个组里有序;然后选择下一个增,一直到d1为1也就是所有数据放到同一个组里直接插入排序排序完成
冒泡排序
public static void BubSort(int A[]) {
for(int i=0;i<A.length;i++) {
for(int j=0;j<A.length-1-i;j++) {
if(A[j]>A[j+1]) {
int tmp=A[j];
A[j]=A[j+1];
A[j+1]=tmp;
}
}
}
}
快速排序
- 思想:快速排序是冒泡排序的一种,多趟排序选择一个记录key,将小于该记录的数据放在key之前,大于key的数放在后面,然后对key前面的和之后的快速排序。平均复杂度:o(nlgn),最坏情况退化为冒泡排序(n^2);不稳定的算法
public static void QuickSort(int A[],int begin,int end) {
int i=begin,j=end;
if(i>=j)
return;
int key=A[i];
while(i<j) {
while(i<j&&A[j]>key)
j--;
if(i<j&&A[j]<=key) {
A[i]=A[j];
i++;
}
while(i<j&&A[i]<key)
i++;
if(i<j&&A[i]>=key) {
A[j]=A[i];
j--;
}
}
A[i]=key;
QuickSort(A,begin,i-1);
QuickSort(A,i+1,end);
}
选择排序
- 思想:从未排序中选择最小元素放到已排序数组部分后
- 时间复杂度:o(n^2)
public static void SelectSort(int A[]) {
for(int i=0;i<A.length;i++) {
int minindex=i;
for(int j=i;j<A.length;j++) {
if(A[j]<A[minindex])
minindex=j;
}
int tmp=A[minindex];
A[minindex]=A[i];
A[i]=tmp;
}
}
堆排序
- 思想:利用双亲和孩子节点之间的关系调整完全二叉树,使它最大值(或者最小值)最顶部,每个顶部节点都是最值。平均复杂度,最坏、最好复杂度都是o(nlgn)。但是每次插入元素都要重新调整
package com.hui.sort;
public class HeapSort {
public void heapSort(int []array) {
matHeapAdjust(array);
for(int i=array.length-1;i>0;i--) {
int tmp=array[0];
array[0]=array[i];
array[i]=tmp;
heapAdjust(array,1,i);
}
}
private void heapAdjust(int[] array, int s, int m) {
// TODO Auto-generated method stub
int tmp,i,largest;
tmp=array[s-1];
for(i=2*s;i<=m;i*=2) {
if(i<m&&array[i-1]<array[i]) {
largest=i;
i++;
}else {
largest=i-1;
}
if(tmp>=array[largest])
break;
array[s-1]=array[largest];
s=largest+1;
}
array[s-1]=tmp;
}
private void matHeapAdjust(int[] array) {
// TODO Auto-generated method stub
for(int i=array.length/2;i>0;i--)
heapAdjust(array,i,array.length);
}
}
归并排序
- 思想:将多个有序表归并成新的有序表。
- 空间复杂度o(n);稳定;时间复杂度o(nlogn)
- 适用于大数据排序,比如说5000万个数排序而且内存不够。
public static void MergSort(int a[],int begin,int end,int[] tmp) {
if(begin<end) {
int mid=(begin+end)/2;
MergSort(a,begin,mid,tmp);
MergSort(a,mid+1,end,tmp);
MergArray(a,begin,mid,mid+1,end,tmp);
}
}
private static void MergArray(int[] a, int Lbegin, int Lend, int Rbegin, int Rend, int[] tmp) {
// TODO Auto-generated method stub
int i=Lbegin,j=Rbegin,k=0;
while(i<=Lend&&j<=Rend) {
if(a[i]<a[j])
tmp[k++]=a[i++];
else
tmp[k++]=a[j++];
}
while(i<=Lend)
tmp[k++]=a[i++];
while(j<=Rend)
tmp[k++]=a[j++];
for(int h=0;h<k;h++)
a[Lbegin+h]=tmp[h];
}
归并排序变形
-
题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007 -
输入描述:
题目保证输入的数组中没有的相同的数字 -
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
public class Solution {
int count=0;
public int InversePairs(int [] array) {
if(array==null||array.length==0)
return 0;
mergeSort(array,0,array.length-1);
return count;
}
private void mergeSort(int a[],int left,int right){
if(left>=right)
return;
int mid=(left+right)/2;
mergeSort(a,left,mid);
mergeSort(a,mid+1,right);
merge(a,left,mid,right);
}
private void merge(int a[],int left,int mid,int right){
int temp[]=new int[right-left+1];
int l=mid,r=right,m=mid;
int t=right-left;
while(l>=left&&r>mid){
if(a[l]>a[r]){
count+=r-mid;
temp[t--]=a[l--];
if(count>=1000000007)
count=count%1000000007;
}else{
temp[t--]=a[r--];
}
}
while(l>=left){
temp[t--]=a[l--];
}
while(r>mid){
temp[t--]=a[r--];
}
for(int i=0;i<right-left+1;i++)
a[left+i]=temp[i];
}
}
网友评论