常用几种排序算法

三种时间复杂度为O(n2)的排序算法

    插入排序

    插入排序的主要思想是:每一次得到一个新的元素,就和原来已经排序好的序列对比,然后将这个新的元素插入到正确的位置,具体的代码实现:

 
 
void insertSort(int a[],int length)
{
	if(a==NULL||length<=0) return;
	for(int i=1;i<length;i++)
	{
		int j=i;
		while(j-1>=0&&a[j-1]>a[j])
		{
			int tmp=a[j-1];
			a[j-1]=a[j];
			a[j]=tmp;
			j--;
		}
	}

}
 
 

    插入排序的最差情况,这里做的是从小到大的排列,假设对于第k次循环,需要比较的k前的元素和第k个的大小,需要将第k个元素移动到小于等于的位置,所有对于最差的情况,应该是该数组逆序排列,从第i(i>=1)个元素开始,每一个元素,要移动i位,最差的时间复杂度应该是1+2+3+....+n-1 ,所以应该是O(n2).

    最好的时间复杂读,是已经排好序,也就是只需要遍历一遍,时间复杂度为O(n);

    同样的道理,平均情况应该也是O(n2).

    冒泡排序

    冒泡排序的主要思想是,小的下沉,大的上浮。

    代码实现如下:

void bubSort(int a[],int length)
{
	if(a==NULL||length<=0) return;
	for(int i=1;i<length;i++)
	{
		for(int j=i;j>0;j--)
		{
			if(a[j]<a[j-1])
			{
				int tmp=a[j];
				a[j]=a[j-1];
				a[j-1]=tmp;
			}
		}
	}
}

    通过代码可以看出,冒泡排序的时间复杂度为O(n2)

选择排序

    主要的思想是:从数组中选择一个最小的,放在最前的位置,然后选择次小的,依次下去,这样就形成了一个有序的数组。

    代码实现:

void selectSort(int a[],int length)
{
	if(a==NULL||length<=0) return;
	for(int i=0;i<length;i++)
	{
		int min=a[i];
		int pos=i;
		for(int j=i+1;j<length;j++)
		{
			if(a[j]<min)
			{
				min=a[j];
				pos=j;
			}
		}		
		//交换最小的
		int tmp=a[i];
		a[i]=min;
		a[pos]=tmp;
	}
}

    可以看出,,选择排序最好、最差、平均都是O(n2);

一下是三种简单排序算法的比较

    Shell排序

        主要的思想:Shell排序是插入排序的改进,由于插入排序是相邻元素之间的比较,Shell排序主要的是将比较的元素进行非增量比较,也就是将元素进行分为多个序列,然后进行比较,但是要注意的是,在最后,还要进行一次增量为1的比较,也就是常规的插入排序。

        代码实现

void shellInsertSort(int a[],int length,int incr)
{
	for(int i=incr;i<length;i+=incr)
	{
		int j=i;
		while(j-incr>=0&&a[j-incr]>a[j])
		{
			int tmp=a[j-1];
			a[j-1]=a[j];
			a[j]=tmp;
			j-=incr;
		}
	}
}

void shellSort(int a[],int length)
{
	for(int i=length;i>2;i=i/2)
		for(int j=0;j<i;j++)
			shellInsertSort(a,length-j,i);
	shellInsertSort(a,length,1);
}

    Shell排序的最好、最坏时间复杂度为O(n2),平均时间复杂为O(n1.5)

快速排序

    快速排序的主要思想:主要是利用分治的思想,将数组分为两部分,左边的部门小于a[k],右边的元素大于等于a[k-1],然后重复以上步骤。

    代码实现:

public class QuickSort {

    public static void quickSort(int arr[],int _left,int _right){
        int left = _left;
        int right = _right;
        int temp = 0;
        if(left <= right){   //待排序的元素至少有两个的情况
            temp = arr[left];  //待排序的第一个元素作为基准元素
            while(left != right){   //从左右两边交替扫描,直到left = right

                while(right > left && arr[right] >= temp)  
                     right --;        //从右往左扫描,找到第一个比基准元素小的元素
                  arr[left] = arr[right];  //找到这种元素arr[right]后与arr[left]交换

                while(left < right && arr[left] <= temp)
                     left ++;         //从左往右扫描,找到第一个比基准元素大的元素
                  arr[right] = arr[left];  //找到这种元素arr[left]后,与arr[right]交换

            }
            arr[right] = temp;    //基准元素归位
            quickSort(arr,_left,left-1);  //对基准元素左边的元素进行递归排序
            quickSort(arr, right+1,_right);  //对基准元素右边的进行递归排序
        }        
    }
    public static void main(String[] args) {
        int array[] = {10,5,3,1,7,2,8};
        System.out.println("排序之前:");
        for(int element : array){
            System.out.print(element+" ");
        }
        
        quickSort(array,0,array.length-1);

        System.out.println("\n排序之后:");
        for(int element : array){
            System.out.print(element+" ");
        }

    }

}

    快速排序的最好和平均时间O(nlogN),最差情况是O(n2).

堆排序

    主要的思想:利用堆的性质。

    堆排序在上几节中已经实现,这里只是讲解最坏、最差、平均的时间复杂度为O(nlogN);

归并排序

void mergeSort(int a[],int tmp[],int left,int right)
{
	int mid=(left+right)/2;
	if(left==right) return;
	mergeSort(a,tmp,left,mid);
	mergeSort(a,tmp,mid,right);
	for(int i=left;i<=right;i++)
	{
		tmp[i]=a[i];
	}
	int i1=left,j=mid+1;
	for(int i=left;i<=right;i++)
	{
		if(i1==mid+1){
			//这里左边的数组使用完毕
			a[i]=tmp[j++];
		}
		else if(j>right)
		{
			a[i]=tmp[i1++];
		} 
		else if(a[i1]<a[j])
		{
			a[i]=a[i1++];
		}
		else
		{
			a[i]=a[j++];
		}
	}
}
    对于归并排序,划分的深度为logN,无论好坏,平均,这个算法的平均复杂度为(nlongN)



猜你喜欢

转载自blog.csdn.net/oeljeklaus/article/details/80154008