排序查找算法大总结

(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/74058248冷血之心的博客)

温故而知新,可以为师矣

“深入理解”—选择排序算法

“深入理解”—交换排序算法

“深入理解”—插入排序算法

“深入理解”—归并排序算法

    二分查找算法

不对之处请各位指出,感谢。

 

import org.junit.Test;
/**
 * 总结排序算法:
 * 冒泡排序、快速排序
 * 直接插入排序、折半插入排序、希尔排序
 * 选择排序、堆排序
 * 归并排序
 * 二分查找算法(递归、迭代)
 * @author ywq
 *
 *
 */
public class Solution {
	@Test
	public void sort(){
		int[] num = {10,2,3,1,67,49,38,65,97,76,13,27,0};
//		for (int i : num) {
//			System.out.print(i+" ");
//		}
//		System.out.println();
		bubbleSort(num);
//		quickSort(num, 0, num.length-1);
		
//		insertSort(num);
//		shellSort(num);
//		halfinsertSort(num);
		
//		selectSort(num);
//		heapSort(num);
		
//		mergeSort(num, 0, num.length-1);
		
		System.out.println(halfSearch2(num,0,num.length-1,3));
		for (int i : num) {
			System.out.print(i+" ");
		}
	}
	
	/**
	 * 从后往前的冒泡排序
	 * @param num
	 */
	public void bubbleSort(int[] num){
		if(num==null)
			return;
		// 设置标志位
		boolean flag = true;
		for (int i = 0; i < num.length&&flag; i++) {
			flag = false;
			for (int j = num.length-1; j > 0; j--) {
				if(num[j]<num[j-1]){
					int temp = num[j];
					num[j] = num[j-1];
					num[j-1] = temp;
					flag = true; // 有交换时,将标志位重置为true
				}
			}
		}
	}
	/**
	 * 快速排序
	 * @param num
	 * @param left
	 * @param right
	 */
	public void quickSort(int[] num, int left, int right) {
        if (num == null)
            return;
        //如果左边大于右边,则return,这里是递归的终点,需要写在前面。
        if (left >= right) {
            return;
        }
        int i = left;
        int j = right;
        int temp = num[i];
        //此处开始进入遍历循环
        while (i < j) {
            //从右往左循环
            while (i < j && num[j] >= temp) {//如果num[j]大于temp值,则pass,比较下一个
                j--;
            }
            num[i] = num[j];
            while (i < j && num[i] <= temp) {
                i++;
            }
            num[j] = num[i];


            num[i] = temp; // 此处不可遗漏,将基准值插入到指定位置
        }
        quickSort(num, left, i - 1);
        quickSort(num, i + 1, right);
    }
	
	
	/**
	 * 直接插入排序算法
	 * @param num
	 */
	public void insertSort(int[] num){
		if(num==null)
			return ;
		for (int i = 1; i < num.length; i++) {
			int temp = num[i] ;
			int j ;       // 记得是j>=0不要忘记等号,否则,前两个将不参与比较
			for (j = i-1; j >= 0&&num[j]>temp; j--) {
				num[j+1] = num[j];  //将前面的较大元素往后移动
			}
				num[j+1] = temp;  // 将num[i]放在指定位置
		}
	}
	/**
	 * 希尔排序,分组的直接插入排序
	 * 多加了一成循环,增量d的初始值为数组长度的一半
	 * @param num
	 */
	public void shellSort(int[] num){
		if(num==null)
			return ;
		for(int d = num.length/2 ; d > 0 ; d=d/2){
			for(int i = d;i<num.length;i+=d){
				int temp = num[i];
				int j;
				for(j = i-d;j>=0&&num[j]>temp;j-=d){
					num[j+d] = num[j];
				}
					num[j+d] = temp;
			}
		}
	}
	/**
	 * 折半插入排序:
	 * left = 0;
	 * right = i-1; 目标是将第i个元素插入到前面的某个位置,所以right为i-1
	 * @param num
	 */
	public void halfinsertSort(int[] num){
		if(num==null)
			return ;
		for (int i = 1; i < num.length; i++) {
			int left = 0;
			int right = i-1;
			int temp = num[i] ;
			while(left<=right){
				int mid = (left+right)/2;
				if(num[mid]>temp){
					right = mid-1;
				}else if(num[mid]<=temp){
					left = mid+1;
				}
			}
			// 经过上边的循环,知道num[i]应该插入到left位置
			int j ;      
			for (j = i-1; j >= left; j--) {
				num[j+1] = num[j];  //将前面的较大元素往后移动
			}
				num[left] = temp;  // 将num[i]放在指定位置
		}
	}
	
	
	
	/**
	 * 选择排序:外层循环控制着趟数,每趟的num[i]我们认为是最小值
	 * @param num
	 */
	public void selectSort(int[] num){
		if(num==null)
			return ;
		for(int i = 0;i<num.length;i++){
			// 内层循环j=i+1,外层循环控制着循环次数。
			// 即每趟中num[i]这个值就是本趟的最小值。i位置上是最小值 
			for (int j = i+1; j < num.length; j++) {
				if(num[i]>num[j]){
					int temp = num[i];
					num[i] = num[j];
					num[j] = temp;
				}
			}
		}
	}
	/**
	 * 堆排序:
	 * 1、构建大顶堆
	 * 2、交换堆顶和末尾元素
	 * 3、继续构建大顶堆
	 * @param num
	 */
	public void heapSort(int[] num){
		if(num==null)
			return ;
		// 构建大顶堆
		for (int parent = (num.length)/2; parent>=0; parent--) {
			getMaxHeap(num,parent,num.length-1);
		}
		// 取堆顶元素进行交换,重新构建大顶堆
		for(int t = num.length-1;t>0;t--){
			swap(num,0,t);
			getMaxHeap(num, 0, t-1);
		}
	}
	/**
	 * 交换数组中的两个位置的元素
	 * @param num
	 * @param i
	 * @param t
	 */
	private void swap(int[] num, int i, int t) {
		if(num==null)
			return ;
		int temp = num[i];
		num[i] = num[t];
		num[t] = temp;
	}
	/**
	 * 构建大顶堆的方法  
     * s 代表拥有左右孩子节点的节点,即本次要调整位置的节点  
     * length 代表当前堆的长度
	 * @param num
	 * @param s
	 * @param length
	 */
	private void getMaxHeap(int[] num, int s, int length) {
		if(num==null)
			return ;
		int temp = num[s];
		 // j=2*j+1是要找到j的孩子节点 
		for(int j = 2*s+1;j<length;j=2*j+1){ // j=2*s+1为s节点的左孩子,j+1为s节点的右孩子 
			// 将j指向子节点中较大值
			if(num[j]<num[j+1])
				j++;
			// 判断父节点和子节点最大值的关系
			if(temp>=num[j])
				break ; // 如果s节点的值大于其最大的孩子节点值,则,循环结束,本次不做任何改变
			// 否则
			num[s] = num[j]; // 否则将较大的孩子节点的值赋值给父节点   
			s = j; // 将j的值赋值给s,即j成为了下一波的父节点,继续比较
		}
		num[s] = temp; // 将temp放在指定位置
	}
	
	
	
	/**
	 * 归并排序:
	 * 将两个(或两个以上)有序表合并成一个新的有序表 即把待排序序列分为若干个子序列, 
     *     每个子序列是有序的。然后再把有序子序列合并为整体有序序列  
	 * @param num
	 * @param left
	 * @param right
	 */
	public void mergeSort(int[] num,int left,int right){
		if(num==null)
			return ;
		int mid = (left+right)/2;
		if(left<right){
			// 处理左边
			mergeSort(num, left, mid);
			// 处理右边
			mergeSort(num, mid+1, right);
			// 左右归并
			merge(num, left, mid, right);
		}
	}
	private void merge(int[] num, int left, int mid, int right) {
		// 定义一个辅助数组,所以该算法的空间复杂度为O(N)
		int[] temp = new int[right-left+1];
		int i = left;
		int j = mid+1;
		int k = 0;
		// 找出较小值元素放入temp数组中
		while(i<=mid&&j<=right){
			if(num[i]<num[j])
				temp[k++] = num[i++];
			else
				temp[k++] = num[j++];
		}
		// 处理较长部分
		while(i<=mid){
			temp[k++] = num[i++];
		}
		while(j<=right){
			temp[k++] = num[j++];
		}
		// 使用temp中的元素覆盖num中的元素
		for(int k2 = 0;k2<temp.length;k2++){
			num[k2+left] = temp[k2];
		}
	}
	
	/**
	 * 基于循环的二分查找实现算法
	 * @param num
	 * @param target
	 * @return
	 */
	public int halfSearch(int[] num,int target){
		if(num==null)
			return -1;
		int left = 0;
		int right = num.length-1;
		while(left<=right){
			int mid = (left+right)/2;
			int midValue = num[mid];
			if(midValue>target)
				right = mid-1;
			else if(midValue<target)
				left = mid+1;
			else
				return mid;
		}
		return -1;
	}
	/**
	 * 基于递归实现的二分查找算法
	 * @param num
	 * @param left
	 * @param right
	 * @param target
	 * @return
	 */
	public int halfSearch2(int[] num,int left,int right,int target){
		if(num==null)
			return -1;
		int mid = (left+right)/2;
		int midValue = num[mid];
		if(left<=right){
			if(midValue>target)
				return halfSearch2(num, left, mid-1, target);
			else if (midValue<target) 
				return halfSearch2(num, mid+1, right, target);
			else
				return mid;
		}
		return -1;
	}
}

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

温柔狠角色

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值