java基础算法:二分、冒泡,选择,插入,快速排序。


这里默认大家已经了解这些算法
本文参考b站黑马视频

二分查找

先定义二分查找方法
/**
* a: 待排序的数组
* t: 需要查找的数字
* return:数组中与t匹配的元素的索引
*/
public void int binarySearch(int[] a, int t){
	// 左索引  右索引  中间索引
	int l = 0, r = a.length - 1, m;
	while(l <= r) {
	    // 这样写可以防止整数溢出现象
		m = (l + r)>>>1;
		if(a[m] == t) {
			return m;
		}else if(a[m] > t) {
			r = m - 1;
         }else{
			l = m + 1;
		}
	}
	// 如果没有找到则返回-1
	return -1;
}

冒泡排序(1:普通版 2:加强版 3:最终版)

// 首先先定义一个给定数组和两个索引,交换两个索引位置的方法
public static void swap(int[] a, int i, int j) {
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}
  1. 普通版
public static void bubbleOne(int[] a) {
for(int j = 0; j < a.length - 1; j++) {
	for(int i = 0; i < a.length - 1 -j; i++) {
		if(a[i] > a[i + 1]) {
			swap(a, i, i + 1);
			}	
     	}
	}
	System.out.println(Arrays.toString(a));
}
  1. 加强版
    public static void bubble_two(int[] a) {
    	// 判断是否发生交换 减少冒泡次数
        boolean swapped = false; 
        for (int j = 0; j < a.length - 1; j++) {
            // 一次冒泡
            for (int i = 0; i < a.length - 1 - j; i++) {
                if (a[i] > a[i + 1]) {
                    swap(a, i, i + 1);
                    // 如果发生交换
                    swapped = true;
                }
            }
            // 如果冒泡一波下来没有发生任何交换,说明数组已经成了有序数组,不必进行后面的冒泡操作了
            if (!swapped) {
                break;
            }
        }
        System.out.println(Arrays.toString(a));
    }
  1. 最终版
    public static void bubble_three(int[] a) {
        int n = a.length - 1;
        while (true){
            int last = 0; // 表示最后一次交换索引位置
            for (int i = 0; i < n; i++) {
                if (a[i] > a[i + 1]) {
                    swap(a, i, i + 1);
                    // 每次交换记录交换的位置i
                    last = i;
                }
            }
            n = last;
            if (n == 0) {
                break;
            }
        }
        System.out.println(Arrays.toString(a));
    }

选择排序

// 首先先定义一个给定数组和两个索引,交换两个索引位置的方法
public static void swap(int[] a, int i, int j) {
	int t = a[i];
	a[i] = a[j];
	a[j] = t;
}

public void selection(int[] a) {
	for(int i = 0; i < a.length - 1; i++){
		int s = i;
		for(int j = s + 1; j < a,length; j++) {
			if(a[s] > a[j]) {
				s = j;
			}
		}
		// 这里交换其实也是做了优化的,不建议在上面的if外进行交换,浪费性能,等上面的for循环结束直接找到最小的进行最后交换就行了
		if(s != i) {
			swap(a, s, j);
		}	
	}
	System.out.println(Arrays.toString(a));
}

插入排序

public static void insert(int[] a) {
	// i 代表待插入元素的索引
	for(int i = 1; i < a.length; i++) {
		// 代表待插入的元素值
		int t = a[i];
		// 代表已排序区域的元素索引
		int j = i - 1;
		while(j >= 0) {
			if(a[j] > t){
				// 向后移动一位
				a[j + 1] = a[j];
			}else {
				break;	
			}
			j--;
		}	
		a[j + 1] = t;	
	}
	System.out.println(Arrays.toString(a));
}
    public static void swap(int[] a, int i, int j) {
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

快速排序(1:单边循环 2:双边循环)

  1. 单边循环
   /**
    * 实现分区
    *
    * @param a 待分区的数组
    * @param l 下边界
    * @param h 上边界
    *          return 基准点元素所在的正确索引
    */
   private static int partition(int[] a, int l, int h) {
       // 基准点元素
       int pv = a[h];
       // 比基准点小的元素都交换到i的左侧
       int i = l;
       for (int j = l; j < h; j++) {
           if (a[j] < pv) {
               if (i != j) {
                   swap(a, i, j);
               }
               i++;
           }
       }
       // 最后基准点与i交换,i即为分区位置
       if (i != h) {
           swap(a, h, i);
       }
       // 返回值代表了基准点元素所在的正确索引,用它确定下一轮分区的边界
       return i;
   }
   // 通过递归不断缩小分区范围,最终实现
   public static void quick(int[] a, int l, int h) {
       if (l >= h) { // 表示区间内没有元素或者只有一个元素
           System.out.println(Arrays.toString(a));
           return;
       }
       // 第一次分区后的基准点的正确索引值
       int p = partition(a, l, h);
       // 左边分区的范围确定
       quick(a, l, p - 1);
       // 右边分区的范围确定
       quick(a, p + 1, h);
   }
   public static void swap(int[] a, int i, int j) {
       int t = a[i];
       a[i] = a[j];
       a[j] = t;
   }
  1. 双边循环
	    /**
     * 实现分区
     *
     * @param a 待分区的数组
     * @param l 下边界
     * @param h 上边界
     *          return 基准点元素所在的正确索引
     */
    private static int partition(int[] a, int l, int h) {
        // 双边循环大多以左边界为基准点
        // 基准点
        int pv = a[l];
        // 左边界
        int i = l;
        // 右边界
        int j = h;
        while (i < j) {
            // j 从右向左找比基准点小的元素
            while (i < j && a[j] > pv) {
                j--;
            }
            // i 从左向右找比基准点大的元素
            while (i < j && a[i] <= pv) {
                i++;
            }
            swap(a, i, j);
        }
        swap(a, l, j);
        System.out.println(Arrays.toString(a) + " j=" + j);

        return j;
    }

    // 通过递归不断缩小分区范围,最终实现
    public static void quick(int[] a, int l, int h) {
        if (l >= h) { // 表示区间内没有元素或者只有一个元素
            return;
        }
        // 第一次分区后的基准点的正确索引值
        int p = partition(a, l, h);
        // 左边分区的范围确定
        quick(a, l, p - 1);
        // 右边分区的范围确定
        quick(a, p + 1, h);
    }
    public static void swap(int[] a, int i, int j) {
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值