数据结构与算法-排序&查找

冒泡排序

将最大的每一轮放到最右边

  /** 
     * 冒泡排序
     *O(n^2)
     * @param arr
     * @return
     */
    public static void bubbleSort(int[] arr) {
        int count = 0;//交换次数
        for (int i = 0; i < arr.length - 1; i++) {
            boolean flag = false;//一趟下来是否进行过交换,如果没有就说明前面的都是有序的就退出,{1,2,3,4,5}
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    count++;
                    flag = true;
                    swap(arr, j);
                }
            }
            if (!flag) {
                System.out.println(count);
                return ;
            }
        }
        System.out.println(count);
       
    }

    private static void swap(int[] arr, int i) {
        int tem = arr[i];
        arr[i] = arr[i + 1];
        arr[i + 1] = tem;
    }
  • 稍微优化就是判断一下前面几个是否是已经是有序的,用一个flag变量来判断;

选择排序

找出最小或者最大的放到它应该放的位置;

 /**
     * 选择排序
     *找出最大或者最小的数,放到应该放的位置
     *给每个元素找到合适的位置
     *O(n^2)
     * @param arr
     */ 
private static void selectSort(int[] arr) {
        for (int j = 0; j < arr.length - 1; j++) {
            int minIndex = j;
            int min = arr[j];
            for (int i = j + 1; i < arr.length; i++) {
                if (min > arr[i]) {
                    //修改上面的符号可以修改排序顺序
                    min = arr[i];
                    minIndex = i;
                }
            }
            if (minIndex != j) {
                //一轮后,将最小值交换
                arr[minIndex] = arr[j];
                arr[j] = min;
            }
        }
    }

插入排序

上来将第一个数当作有序,将其后的每一个无序插入前面已经整理了有序的适当位置;

 /**
     * 插入排序 ,将右边无序的插入左边有序的
     *
     * @param arr
     */
    private static void insertSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            //从第二个元素起
            int insertVal = arr[i];
            //val的值
            int insertIndex = i - 1;
            while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
                //假如前面的比要当前插入值大,就把前面的值往后挪,这样挪的目的是,要插入的元素已经保存了,然后继续往前比较
                //直到存在一个比他小的为止或者要插入的位置头部索引
                arr[insertIndex + 1] = arr[insertIndex];
                insertIndex--;
            }
            //最后将插入值放入索引位置
            arr[insertIndex + 1] = insertVal;
        }
    }

希尔排序

 /**
     * 希尔排序,分组交换,逐渐将分组的个数增加直到分的组到最后只有一个
     * * 交换法
     *
     * @param arr
     */
    private static void shellSort(int[] arr) {

        // 假设 length 为8 ,第一次 分组gps/2 每个组长度为2 第二次gps/2/2 每个组长度为4 gps为组的长度

        for (int gps = arr.length / 2; gps > 0; gps /= 2) {
            //得出有多少组,直到分为一个组
            for (int j = gps; j < arr.length; j++) {
                //对所有得到的组进行排序
                for (int i = j - gps; i >= 0; i -= gps) {
                    //对单一的一个组排序
                    if (arr[i] > arr[i + gps]) {
                        int temp = arr[i];
                        arr[i] = arr[i + gps];
                        arr[i + gps] = temp;
                    }
                }
            }
        }
    }

    /**
     * 希尔排序 移位法
     *
     * @param arr
     */
    private static void shellSortByMove(int[] arr) {

        // 假设 length 为8 ,第一次 分组gps/2 每个组长度为2 第二次gps/2/2 每个组长度为4 gps为组的长度

        for (int gps = arr.length / 2; gps > 0; gps /= 2) {
            for (int i = gps; i < arr.length; i++) {
                int j = i;
                int temp = arr[j];
                while (j - gps >= 0 && temp < arr[j - gps]) {
                    arr[j] = arr[j - gps];
                    j -= gps;
                }
                //退出while 找到插入位置
                arr[j] = temp;
            }
        }
    }

快速排序 *

 /**
     * 快速排序 
     * @param arr
     * @param left 左指针
     * @param right 右指针
     */
//left=0;right=arr.length;
    private static void quickSort(int[] arr, int left, int right) {
        int l = left;
        int r = right;
        int pivot = arr[(left + right) / 2];
        int temp;
        while (l < r) {
            //在左边找到一个比中值大的
            while (arr[l] < pivot) {
                l += 1;
            }
            //在右边找到一个比中值小的
            while (arr[r] > pivot) {
                r -= 1;
            }

            if (l >= r) {
                break;
            }
            //交换
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            if (arr[l] == pivot) {
                r--;
            }
            if (arr[r] == pivot) {
                l++;
            }
        }
        if (l == r) {
            l++;
            r--;
        }
        //向左递归
        if (left < r) {
            quickSort(arr, left, r);
        }
        //向右递归
        if (right > l) {
            quickSort(arr, l, right);
        }
    }

归并排序

  //分+合方法
    public static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if(left < right) {
            int mid = (left + right) / 2; //中间索引
            //向左递归进行分解
            mergeSort(arr, left, mid, temp);
            //向右递归进行分解
            mergeSort(arr, mid + 1, right, temp);
            //合并
            merge(arr, left, mid, right, temp);

        }
    }
    /**
     * 归并排序
     *
     * @param arr
     */
    private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        int i = left; // 初始化i, 左边有序序列的初始索引
        int j = mid + 1; //初始化j, 右边有序序列的初始索引
        int t = 0; // 指向temp数组的当前索引
        //(一)
        //先把左右两边(有序)的数据按照规则填充到temp数组
        //直到左右两边的有序序列,有一边处理完毕为止
        while (i <= mid && j <= right) {//继续
            //如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
            //即将左边的当前元素,填充到 temp数组
            //然后 t++, i++
            if (arr[i] <= arr[j]) {
                temp[t] = arr[i];
                t += 1;
                i += 1;
            } else { //反之,将右边有序序列的当前元素,填充到temp数组
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }

        //(二)
        //把有剩余数据的一边的数据依次全部填充到temp
        while (i <= mid) { //左边的有序序列还有剩余的元素,就全部填充到temp
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }

        while (j <= right) { //右边的有序序列还有剩余的元素,就全部填充到temp
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }


        //(三)
        //将temp数组的元素拷贝到arr
        //注意,并不是每次都拷贝所有
        t = 0;
        int tempLeft = left; //
        //第一次合并 tempLeft = 0 , right = 1 //  tempLeft = 2  right = 3 // tL=0 ri=3
        //最后一次 tempLeft = 0  right = 7
        while (tempLeft <= right) {
            arr[tempLeft] = temp[t];
            t += 1;
            tempLeft += 1;
        }

    }

基数排序

//基数排序方法
	public static void radixSort(int[] arr) {
		
		//根据前面的推导过程,我们可以得到最终的基数排序代码
		
		//1. 得到数组中最大的数的位数
		int max = arr[0]; //假设第一数就是最大数
		for(int i = 1; i < arr.length; i++) {
			if (arr[i] > max) {
				max = arr[i];
			}
		}
		//得到最大数是几位数
		int maxLength = (max + "").length();
		
		
		//定义一个二维数组,表示10个桶, 每个桶就是一个一维数组
		//说明
		//1. 二维数组包含10个一维数组
		//2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
		//3. 名明确,基数排序是使用空间换时间的经典算法
		int[][] bucket = new int[10][arr.length];
		
		//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
		//可以这里理解
		//比如:bucketElementCounts[0] , 记录的就是  bucket[0] 桶的放入数据个数
		int[] bucketElementCounts = new int[10];
		
		
		//这里我们使用循环将代码处理
		
		for(int i = 0 , n = 1; i < maxLength; i++, n *= 10) {
			//(针对每个元素的对应位进行排序处理), 第一次是个位,第二次是十位,第三次是百位..
			for(int j = 0; j < arr.length; j++) {
				//取出每个元素的对应位的值
				int digitOfElement = arr[j] / n % 10;
				//放入到对应的桶中
				bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
				bucketElementCounts[digitOfElement]++;
			}
			//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
			int index = 0;
			//遍历每一桶,并将桶中是数据,放入到原数组
			for(int k = 0; k < bucketElementCounts.length; k++) {
				//如果桶中,有数据,我们才放入到原数组
				if(bucketElementCounts[k] != 0) {
					//循环该桶即第k个桶(即第k个一维数组), 放入
					for(int l = 0; l < bucketElementCounts[k]; l++) {
						//取出元素放入到arr
						arr[index++] = bucket[k][l];
					}
				}
				//第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
				bucketElementCounts[k] = 0;
				
			}
			//System.out.println("第"+(i+1)+"轮,对个位的排序处理 arr =" + Arrays.toString(arr));
			
		}
		
	
		
	}

线性查找

/**
 * 直接查找,遍历逐一比对,不需要查找序列有序
 */
private static int seqSearch(int[] arr,int d){
    for (int i : arr) {
        if (arr[i]==d){
           return  i;
        }
    }
    return -1;
}

二分查找

    /**
     * 要求数组有序 ,二分法
     *
     * @param arr
     * @param
     * @return
     */
    private static int binarySearch(int[] arr, int left, int right, int findVal) {
        //给一个出口
        if (left >= right) {
            return -1;
        }

        int mid = (left + right) / 2;
        int midV = arr[mid];

        if (midV < findVal) {
            return binarySearch(arr, mid + 1, right, findVal);
        } else if (midV > findVal) {
            return binarySearch(arr, left, mid - 1, findVal);
        } else {
            return mid;
        }

    }

    /**
     * 要求数组有序 ,二分法,找出查找值的所有索引
     *
     * @param arr
     * @param
     * @return
     */
    private static int[] binarySearchAll(int[] arr, int left, int right, int findVal) {
        int[] result;
        //给一个出口
        if (left >= right) {
            return result = new int[]{-1};
        }

        int mid = (left + right) / 2;
        int midV = arr[mid];

        if (midV < findVal) {
            return binarySearchAll(arr, mid + 1, right, findVal);
        } else if (midV > findVal) {
            return binarySearchAll(arr, left, mid - 1, findVal);
        } else {
            //遍历一下 左边或者右边
            result = new int[arr.length];
            result[0] = mid;
            int i = 0;
            int b = mid - 1;
            while (b > 0 || arr[mid] != findVal) {

                i++;
                result[i] = b;
                b--;
                break;
            }
            //右遍历
            int a = mid + 1;
            while (a < arr.length || arr[mid] != findVal) {

                i++;
                result[i] = a;
               a++;
                break;
            }
            return result;
        }

    }

插值查找

/**
     * 插值 二分
     *
     * @param arr
     * @param left
     * @param right
     * @param findVal
     * @return
     */
    private static int binaryInsertValueSearch(int[] arr, int left, int right, int findVal) {
        //给一个出口
        if (left >= right || findVal < arr[0] || findVal > arr[arr.length - 1]) {
            return -1;
        }
        //mid 通过插值近似求出来,数值分析
        int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
        int midV = arr[mid];

        if (midV < findVal) {
            return binarySearch(arr, mid + 1, right, findVal);
        } else if (midV > findVal) {
            return binarySearch(arr, left, mid - 1, findVal);
        } else {
            return mid;
        }

    }

斐波那契查找

根据斐波那契公式的特性:

F(k)=F(k-1)+F(k-2)

=> F(k)-1 = F(k-1) -1 +F(k-2)-1 + 1 最后一个 1 是留给mid 的


在这里插入图片描述

/**
     * 斐波那契查找 mid的值为黄金分割点附近
     mid=low+F(k-1)+1
     * @param arr
     * @param key
     * @return
     */

    private static int FabonacciSearch(int[] arr, int key) {
        int low = 0;
        int high = arr.length - 1;
        int k = 0;//表示斐波那契分割数值下标
        int mid = 0;
        int f[] = fib();
        //获取斐波那契飞割下标
        while (high > f[k] - 1) {
            k++;
        }
        int[] temp = Arrays.copyOf(arr, f[k]);
        for (int i = high + 1; i < temp.length; i++) {
            temp[i] = arr[high];

        }
        while (low <= high) {
            mid = low + f[k - 1] - 1;
            if (key < temp[mid]) {
                high = mid - 1;
                k--;
            } else if (key > temp[mid]) {
                low = mid + 1;
                k -= 2;
            } else {
                if (mid <= high) {
                    return mid;

                } else {
                    return high;
                }
            }
        }
        return -1;
    }

    /**
     * 创建一个斐波那契数列
     * 20可以修改
     * @return
     */
    public static int[] fib() {
        int[] f = new int[20];
        f[0] = 1;
        f[1] = 1;
        for (int i = 2; i < 20; i++) {
            f[i] = f[i - 1] + f[i - 2];
        }
        return f;
    }
发布了37 篇原创文章 · 获赞 6 · 访问量 4658

猜你喜欢

转载自blog.csdn.net/littlewhitevg/article/details/104560937