常见排序与查找算法

排序

一、交换排序

1.冒泡排序

/**
 * 冒泡排序,需要走(nums.length - 1) 趟
 * 因为每一趟排序完后,最大值已经在最后面了,无需再排
 * 所以每一趟都比上一趟少比较一次,每趟比较(nums.length - 1 - i)次
 * @param nums
 * @return
 */
public static int[] BUBBLESort(int[] nums){
    for (int i = 0; i < nums.length - 1; i++) {
        for (int j = 0; j < nums.length - 1 - i; j++) {
            if (nums[j+1] < nums[j]){
                int temp = nums[j];
                nums[j] = nums[j+1];
                nums[j+1] = temp;
            }
        }
    }
    return nums;
}

2.快速排序

我愿称之为”空位“排序

public static int[] quickSort(int[] nums,int start,int end){
   if (start>=end) return nums;
   //以起始元素为中间元素
   int temp = nums[start];
   int i = start;
   int j = end;
   while (i<j){
       //从工作边开始找比中间元素(起始元素)小或等于的元素,如果没找到就继续往左移动,找到了就将"空位"替换
       //所谓"空位"就是原先的值已经被赋值到其他位置了,这个位置就是一个“空位”
       while (i<j && temp<nums[j]){
           j--;
       }
       nums[i] = nums[j];
       //同样再从左边开始
       while (i<j && temp>=nums[i]){
           i++;
       }
       nums[j] = nums[i];
   }
   nums[i] = temp;
   //递归调用
   quickSort(nums,start,i-1);
   quickSort(nums,i+1,end);
   return nums;
}

二、插入排序

1.直接插入排序

/**
 * 需要走(nums.length - 1)趟,每一趟把第i个值前面的都是一个有序序列(因为每一趟结束后前面的数已经排序好了)
 * 定义一个temp用于存储每次第i个位置的值,然后使用while循环来将第i个位置的值放入有序序列中
 * 每次从第i个位置的值前一个开始找,如果这个数比temp大就往后挪一位
 * @param nums 
 * @return
 */
public static int[] insertSort(int[] nums){
    for (int i = 1; i < nums.length; i++) {
        int temp = nums[i];
        int j = i - 1;
        while (j>=0 && temp < nums[j]){
            nums[j+1] = nums[j--];
        }
        //找到了temp的位置
        nums[j+1] = temp;
    }
    return nums;
}

2.折半插入排序

/*
*折半插入排序法
*/
public static int[] bin_insertSort(int[] nums){
    int i,j;
    int temp;
    for (i=1;i<nums.length;i++){
        temp = nums[i];
        int low =0;
        int high = i-1;
        while (low <= high){
            int mid = (low+high)/2;
            if (temp<nums[mid]){
                high = mid-1;
            }else {
                low = mid+1;
            }
        }
        for (j=i-1;j>=low;j--){
            nums[j+1] = nums[j];
        }
        nums[low] = temp;
    }
    return nums;
}

3.希尔排序

/**
 * 希尔排序(交换法)
 * @param nums
 * @return
 */
public static int[] shellSort(int[] nums){
    for (int gap = nums.length/2; gap >0 ; gap /= 2) {
        for (int i = gap; i < nums.length; i++) {
            for (int j = i-gap; j >=0 ; j -= gap) {
                int temp;
                if (nums[j]>nums[j+gap]){
                    temp = nums[j];
                    nums[j] = nums[j+gap];
                    nums[j+gap] = temp;
                }
            }
        }
    }
    return nums;
}

/**
 * 希尔排序(位移法)
 * @param nums
 * @return
 */
public static int[] shellSort(int[] nums) {
    for (int gap = nums.length / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < nums.length; i++) {
            int j = i;
            int temp = nums[j];
            if (nums[j] < nums[j - gap]){
                while (j - gap >= 0 && nums[j - gap] > temp){
                    nums[j] = nums[j - gap];
                    j -= gap;
                }
                nums[j] = temp;
            }

        }
    }
    return nums;
}

三、选择排序

/**
*需要走(nums.length - 1)趟
* 每一趟假设第 i个数为最小值,记录这个值的索引位置为minIndex
* 再从第i+1个数开始找比minIndex索引位置值更小的数,找到了就把这个更小的数的索引值给minIndex
* 最后判断minIndex是否与假设的最小数值索引i不同,不同则把对应位置的值进行交换
* 这样下来每一趟都把最小值放在了前面
* @param nums
* @return
*/
public static int[] selectSort(int[] nums){
  for (int i = 0; i < nums.length - 1; i++) {
      int minIndex = i;
      for (int j = i+1; j < nums.length; j++) {
          //找出最小数的索引
          if (nums[j]<nums[minIndex]) minIndex = j;
      }
      //若最小值索引发生变化就进行交换
      if (minIndex!=i){
          int temp = nums[i];
          nums[i] = nums[minIndex];
          nums[minIndex] = temp;
      }
  }
  return nums;
}

四、归并排序

public static void mergeSort(int[] nums, int left, int right, int[] temp) {
    if (left<right){
        int mid = (left + right)/2;
        mergeSort(nums,left,mid,temp);
        mergeSort(nums,mid+1,right,temp);
        merge(nums,left,right,mid,temp);
    }
}
public static void merge(int[] nums, int left, int right, int mid, int[] temp) {
    int i = left;
    int j = mid + 1;
    int t = 0;
    while (i <= mid && j <= right) {
        if (nums[i] < nums[j]) {
            temp[t++] = nums[i++];
        }
        if (nums[i] > nums[j]) {
            temp[t++] = nums[j++];
        }
        while (i <= mid && j > right) {
            temp[t++] = nums[i++];
        }
        while (i > mid && j <= right) {
            temp[t++] = nums[j++];
        }
    }
    t=0;
    int tempLeft = left;
    while (tempLeft<=right) {
        nums[tempLeft++] = temp[t++];
    }
}

五、基数排序

/**
 * 先计算出最大数的位数决定需要循环走的趟数
 * 通过定义10个桶分别存放按0~9大小存放 个位、十位/...等
 * 每按一次位上数大小排序后将依次将桶里的数覆盖原数组的值
 * @param nums
 * @return
 */
public static int[] baseSort(int[] nums) {
    //计算最大数
    int max = nums[0];
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > max) {
            max = nums[i];
        }
    }
    //计算出最大位数
    int maxLength = (max + "").length();

    int[][] buckets = new int[10][nums.length];
    int[] posElem = new int[10];
    for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
        for (int j = 0; j < nums.length; j++) {
            int posNum = nums[j] / n % 10;
            buckets[posNum][posElem[posNum]++] = nums[j];
        }
        int index = 0;
        for (int k = 0; k < buckets.length; k++) {
            if (posElem[k] != 0) {
                for (int l = 0; l < posElem[k]; l++) {
                    nums[index++] = buckets[k][l];
                }
            }
            posElem[k] = 0;
        }
    }
    return nums;
}

查找

一、二分查找

/**
 * 每次取中间值(low + high)/2与查询值比较
 * 若查询值大于中间值说明查询值在左边,将high值置于mid - 1,重写计算mid
 * 若查询值小于中间值说明查询值在右边,将low值置于mid + 1,重写计算mid
 * 若相等则直接返回对应下标
 * 当low>high时说明没有查找到对应的值
 * @param nums
 * @param searchVal
 * @return
 */
public static int binarySearch(int[] nums, int searchVal) {
    int low = 0;
    int high = nums.length - 1;
    int mid;
    while (low <= high) {
        mid = (low + high) / 2;
        if (searchVal > nums[mid]) {
            low = mid + 1;
        } else if (searchVal < nums[mid]) {
            high = mid - 1;
        } else {
            return mid;
        }
    }
    return -1;
}
posted @ 2022-07-31 17:11  一只小周皮妖🐯  阅读(95)  评论(0)    收藏  举报