快速排序及优化,堆排序总结(上)

博主重新学习快排并根据左神视频优化。经典快排以最后元素为基准,随机快排随机选数与末尾交换作基准,复杂度通过期望得到,应用更广。优化参考荷兰国旗问题,让相等数归为一类。还介绍了未优化快排、优化快排及基于非递归的快排实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大二时候学的快排和堆排现在忘的差不多了。。。重新学习了下快排并根据左神的视频进行了优化
经典快排是以最后一个元素作为基准点,随机快排是从集合中随机选择一个数和最后一个元素交换作为基准点,因此经典快排和随机快排的代码相差不大,但是随机快排的复杂度是通过期望得到的,是个概率上的复杂度,运用的更广泛。

优化后的快排主要是参考了荷兰国旗问题,将和基准数相等的数归为一类,这样在接下来的排序中,与基准数相同的数就不再需要排序了。

未优化的快速排序

public class test {
	 public static void main(String args[]){
	        int a[] = new int[(int) (Math.random()*20 + 1)];
	        for (int i = 0 ; i<a.length ;i++){
	            a[i] = (int) (Math.random()*100);
	        }
	        quickSort(a);
	        for (int i = 0 ; i<a.length ;i++){
	            System.out.println(a[i]);
	        }
	    }

	    public  static  void quickSort(int a[]){
	        if (a.length < 2 || a==null)
	            return;
	        quickSort(a,0,a.length-1);
	    }

	    public static void quickSort(int a[] , int l ,int r){
	        if(l < r){
	            int p = partition(a, l ,r);
	            quickSort(a, l, p-1);		//递归排序
	            quickSort(a, p+1, r);
	        }
	    }
	    
	    public static int partition(int a[], int l ,int r){
		       int pivot = a[r];
		       int i = l;
		       int j = r;
		      
		        while (i < j){
		        	while(i < j && a[i] <= pivot) i++;
		           while(i < j && a[j] >= pivot)j--;
		           
		          
		           if(i < j)
		        	   swap(a, i , j);
		        }
		        swap(a , r , j);
		        return i;
		    }

	    public static void swap(int arr[],int i,int j){
	    	int tmp = arr[i];
	        arr[i] = arr[j];
	        arr[j] = tmp;
	       
	    }
}

优化过的快排:

public class QuickSort {
    public static void main(String args[]){
        int a[] = new int[(int) (Math.random()*20 + 1)];
        for (int i = 0 ; i<a.length ;i++){
            a[i] = (int) (Math.random()*100);
        }
        quickSort(a);
        for (int i = 0 ; i<a.length ;i++){
            System.out.println(a[i]);
        }
    }

    public  static  void quickSort(int a[]){
        if (a.length < 2 || a==null)
            return;
        quickSort(a,0,a.length-1);
    }

    public static void quickSort(int a[] , int l ,int r){
        if(l < r){
            int p[] = partition(a, l ,r);
            quickSort(a, l, p[0]-1);
            quickSort(a,p[1]+1 , r);
        }
    }

    public static int[] partition(int a[], int l ,int r){
        int less = l-1;  //比基准数小的区域
        int more = r;		//比基准数大的区域
        while (l < more){		
            if (a[l] < a[r]){
                swap(a, ++less , l++);		 //数比基准小,小区域向右移动
            }else if(a[l] > a[r]){
                swap(a, --more, l);       //数比基准大,大区域向左移动
            }else{
                l++;	    	//找到和基准相同的数,相等区域向右移
            }
        }
        swap(a, more ,r);
        return new int []{less+1,more };     //返回相等区域的首尾下标
    }

    public static void swap(int arr[],int i,int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

随机快排和经典快排其实只差了一句代码,在partition函数中随机选一个数作为基准,将这个数和末尾数交换即可

 public static int[] partition(int a[], int l ,int r){
	    	swap(a, l + (int) (Math.random() * (r - l + 1)), r);		//随机交换
	        int less = l-1;  //比基准数小的区域
	        int more = r;		//比基准数大的区域
	        while (l < more){		
	            if (a[l] < a[r]){
	                swap(a, ++less , l++);		 //数比基准小,小区域向右移动
	            }else if(a[l] > a[r]){
	                swap(a, --more, l);       //数比基准大,大区域向左移动
	            }else{
	                l++;	    	//找到和基准相同的数,相等区域向右移
	            }
	        }
	        swap(a, more ,r);
	        return new int []{less+1,more };     //返回相等区域的首尾下标
	    }

基于非递归的快排,实则是将左右指针压入栈得到的,partition函数不需要更改,更改sort函数即可

 public static void quickSort(int a[] , int l ,int r){
        Stack <Integer> temp = new Stack<Integer>();
        temp.push(r);
        temp.push(l);
        int i = l;
        int j = r;
        while (temp.empty() != true){
            i=temp.pop();
            j=temp.pop();
            if(i < j){
                int k = partition(a, i , j);
                if ( k > i){
                    temp.push(k-1);
                    temp.push(i);
                }
                if ( k < j) {
                    temp.push(j);
                    temp.push(k+1);
                }
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值