数据结构-排序算法-分析(Java篇)

  上学期学了数据结构这门课,感觉上的太水了,自己再来重温一遍.

一、插入排序

public static void insertSort(int[] a) {
		int j;
		
		for(int p=1;p<a.length;p++)                          //默认按递增排序
		{
			Integer temp=a[p];     
              for(j=p;j>0&&temp.compareTo(a[j-1])<0;j--) //主要的一步是将要插入a[j]=a[j-1]; //的元素与之前的元素比较直到找到要插入的位置
	 			a[j]=a[j-1];
				a[j]=temp;	                         
//这一步是为了将所有的在被插入位置之后的元素往后挪一位;

}}


时间复杂度O(N2);因为内循环中元素的比较次数对于p的每个值最多是p+1次。

二、希尔排序

public static void shellsort(int[] a) {
		int j;
		
		for(int increment=a.length/2;increment>0;increment/=2)     //increment这里代表的是希尔增量
			for(int i=increment;i<a.length;i++)
		{ 
		        Integer temp=a[i];
			for(j=i;j>=increment&&temp.compareTo(a[j-increment])<0;j-=increment)//这里和插入排序非常相似
			       a[j]=a[j-increment];                         //元素后移的位置不再是相邻的挪移
				                                                     //而是挪了相隔increment的距离
				a[j]=temp;
		}
	}
时间复杂度O(N2);


三、堆排序

	private static int leftChild(int i)
	{
		return 2*i+1;
	}
	
	private static void Down(Integer[] a,int i,int n) 
	{
	   Integer child;
	   Integer temp;
	   
	   for(temp=a[i];leftChild(i)<n;i=child)
	   {
		   child=leftChild(i);
		   if(child!=n-1&&a[child].compareTo(a[child+1])<0)//这一步是为了找到子节点中的较大孩子
			   child++;
		   if(temp.compareTo(a[child])<0)
			   a[i]=a[child];
		   else 
			   break;
	   }
	   a[i]=temp;             //将大节点都按从大到下一层层放下来之后找到合适temp的位置;
	}
	
	public static void heapSort(Integer[] a) {//因为堆是完全二叉树形式的所以我在这把它当作数组来操作了。
		for(int i=a.length/2-1;i>=0;i--)
			Down(a,i,a.length);           //类似初始化堆,把最大值给搞到堆顶了。
		
		for(int i=a.length-1;i>0;i--)     
		{
			int temp=a[0];//实现了将最大值放到堆的最后面的目标;
			a[0]=a[i];    
			a[i]=temp;
			
			Down(a,0,i); //实现Down的过程中不对把刚放到末尾的的最大值进行操作;
		}
	}


时间复杂度为O(N logN);主要时间耗费在构建堆、调整堆上面了,构建堆消耗O(N)的时间,调整堆花了2[log i]的时间,;堆排序是很稳定的

算法。(稳定指的是假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。


四、归并排序

private static void mergeSort(Integer[] a,Integer[] tempArray,int left,int right)
       {
    	   if(left<right) 
    	   {
    		   int middle=(left+right)/2;
    		   mergeSort(a,tempArray,left,middle);   //通过不断的递归,将
    		   mergeSort(a,tempArray,middle+1,right);
    		   merge(a,tempArray,left,middle+1,right);
    	   }
       }
       
       private static void merge(Integer[] a,Integer[] tempArray,int left,int right,int rEnd)
       {
    	   int lEnd=right-1;
    	   int temp=left;
    	  
    	   int sum=rEnd-lEnd+1;
    	   
    	   while(left<=lEnd&&right<rEnd)//a中装着两个数组,以right-1为界;
    		   if(a[left].compareTo(a[right])<=0)//通过left、right指针的移动来
    			   tempArray[temp++]=a[left++];  //将两部分之中较小的那个放到tempArray中
    		   else 
    			   tempArray[temp++]=a[right++];
    	   
    	   while(left<=lEnd)                     //若左边没有放完,则继续直接放入即可
    		   tempArray[temp++]=a[left++];
    	   
    	   while(right<=rEnd)                    //若右边没有放完,则继续直接放入即可
    		   tempArray[temp++]=a[right++];
    	   
    	   for(int i=0;i<sum;i++,rEnd--)         //将tempArray中的值再返回a中
    		   a[rEnd]=tempArray[rEnd];
       }
       public static void mergeSort(Integer[] a)
       {
    	   Integer[] tempArray=(Integer[]) new Comparable[a.length];
    	   
    	   mergeSort(a,tempArray,0,a.length-1);
       }
时间复杂度为O(N logN),在整个算法中还要将tempArray中的数据给拷贝回a中,这里就减慢了速度.


五、快速排序

public static void quicksort(int[] ar, int start, int end){
		int[] array;
		int i = start, j = end;
		if (end-start >= 1){
			int pivot = ar[end];
			while (i< j){
				while (ar[i]<pivot && i<end){
					i++;
				}
				while (ar[j]>=pivot && j>start){
					j--;
				}
				if (i<j){
					swap(ar, i, j);
				}
			} swap(ar, end, i);
			quicksort(ar, start, i-1);
			quicksort(ar, i+1, end);
		} else{
			return;
		}
	}
	public static void swap(int[] ar, int index1, int index2){

		int temp = ar[index1];
		ar[index1] = ar[index2];
		ar[index2] = temp;
	}
快排对pivot的选取比较关键,在一串随机生成的数字中,枢纽可以选在开头,也可选在末尾;但,是如果是一串刚好已经排为相反方向的的数组进行快排时,这就很尴尬了,

快排的时间复杂度为O(NlogN);


六、桶排序与基数排序

	public static void radixSortA(String[] arr,int stringLen)
	{
		final int BUCKETS=256;
		ArrayList<String> [] buckets=(ArrayList<String> [])new ArrayList[BUCKETS];
		for(int i=0;i<BUCKETS;i++)
			buckets[i]=new ArrayList<>();
		
		for(int pos=strLen-1;pos>=0;pos--)
		{
			for(String s:arr)
				buckets[s.charAt(pos)].add(s);
			
			int idx=0;
			for(ArrayList<String> thisBucket:buckets)
			{
				for(String s:thisBucket)
					arr[idx++]=s;
				
				thisBucket.clear();
			}
		}
 	}
上面这个例子是关于字符串的基数排序的实现,用一个ArrayList做桶。时间复杂度
O(NL),这里桶的设定是假设所有字符都是ASCII码,位于Unicode字符集的前256位。


若有不正确之处,望大家指证。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值