排序的总结

排序总结

前言:排序的知识从很早以前就学了,但一直记的不是很牢固,所以今天就把主要的排序都做一些整理,以后需要用到的时候可以进行快速回忆。以下的所有讨论都是基于非递减排序的。

冒泡排序

流程:每次都进行相邻元素的对比,如果前一个数字大于后一个数字,则进行交换,之后对每一对元素都进行相同的操作,经过一轮扫描之后最大的元素就被放置在最后一个元素。然后再从头进行同样的流程,只是接下来扫描的截止位置减少了1个。
代码实现:

public static void bubbleSort(int[] arr) {
    for (int i = arr.length - 1; i >= 0; i--) {
        for (int j = 0; j < i; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

选择排序

流程:第一次从待排序的数字中选择最小的元素,与数组的起始位置进行交换,然后再从接下来的待排序数字中继续寻找最小的元素,与已排序数组的后一个序列进行交换,依此类推。因为每次都将最小的元素插入到已排序数组的后面,所以最后一定能把数组排好序。

public static void selectionSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minIndex = i;
        for (int j = i + 1; j < arr.length; j++) {
            minIndex = arr[j] < arr[minIndex] ? j : minIndex;
        }
        int temp = arr[minIndex];
        arr[minIndex] = arr[i];
        arr[i] = temp;
    }
}

选择排序是O(n ^ 2)的排序算法中唯一一个不稳定的排序,所以通常是最差的选择。

插入排序

流程:插入排序每次都将一个数字插入到一个已经排序好的数组里面,然后继续遍历数组,找到每个数字在前面排好序的数组中正确的位置。

public static void insertionSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
            int temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
}

注意插入排序的时间复杂度会受到数据状况的影响,因为每次插入数据的时候,前面的数组已经排好序了,如果这个数字比前面的所有数字都大,那么就不需要进行插入操作了。如1 2 3 4 5进行插入排序,时间复杂度只有O(1);如果是5 4 3 2 1的话,每一轮都要进行插入操作,时间复杂度是O(n)。

归并排序

流程:将一个数组不断二分,然后把二分的两部分数组合并为一个有序数组,这个有序数组可以跟另一对有序数组进行合并,最终就可以使整个数组变成有序数组了。

public class mergeSort {

    public static void mergeSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }
        mergeSort(arr, 0, arr.length - 1);
    }

    public static void mergeSort(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        int mid = left + ((right - left) >> 1);
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        merge(arr, left, mid, right);
    }

    public static void merge(int[] arr, int left, int mid, int right) {
        int[] help = new int[right - left + 1];
        int p1 = left;
        int p2 = mid + 1;
        int i = 0;
        while (p1 <= mid && p2 <= right) {
            help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
        }
        while (p1 <= mid) {
            help[i++] = arr[p1++];
        }
        while (p2 <= right) {
            help[i++] = arr[p2++];
        }
        for (i = 0; i < help.length; i++) {
            arr[left++] = help[i];
        }
    }
}

堆排序

思路:将数组先建立成一个大根堆,然后每次都将堆顶交换到堆尾,然后将堆的大小减去1,再将新的堆继续调整为大根堆,重复以上过程。

public class heapSort {

    public static void heapSort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr, i);
        }

        int size = arr.length;
        swap(arr, 0, --size);

        while (size > 0) {
            heapify(arr, 0, size);
            swap(arr, 0, --size);
        }
    }

    public static void heapInsert(int[] arr, int i) {
        while (arr[i] > arr[(i - 1) / 2]) {
            swap(arr, i, (i - 1) / 2);
        }
    }

    public static void heapify(int[] arr, int i, int size) {
        int left = i * 2 + 1;
        while (left < size) {
            int largest = left + 1 < size && arr[left] < arr[left + 1] ? left + 1 : left;
            largest = arr[i] < arr[largest] ? largest : i;
            if (largest == i) {
                break;
            }
            swap(arr, i, largest);
            i = largest;
            left = i * 2 + 1;
        }
    }

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

快速排序

思路:快速排序是基于分区的过程的,将一个数字作为分区的基准,经过一轮分区,会把小于该数的数字放到数字的左边,大于该数的数字放在数字的右边。然后基准数字就找到自己的位置,再对基准数字的左边和右边进行以上的递归操作,这样每一轮分区之后,基准数字都会找到自己的位置,到最后就能把数组进行排序了。

桶排序

常见疑问

1.插入排序和选择排序有什么不同?

基于非递增排序说明,插入排序是每次都跟前面相邻的数字进行对比,如果小于的话则进行交换,否则进行下一轮插入查找。而选择排序则是每次都找寻未排序数组中的最小数字去进行交换。

总结

内容概要:文章介绍了DeepSeek在国内智能问数(smart querying over data)领域的实战应用。DeepSeek是一款国内研发的开源大语言模型(LLM),具备强大的中文理解、推理和生成能力,尤其适用于企业中文环境下的智能问答、知识检索等。它具有数据可控性强的特点,可以自部署、私有化,支持结合企业内部数据打造定制化智能问数系统。智能问数是指用户通过自然语言提问,系统基于结构化或非结构化数据自动生成精准答案。DeepSeek在此过程中负责问题理解、查询生成、多轮对话和答案解释等核心环节。文章还详细展示了从问题理解、查询生成到答案生成的具体步骤,并介绍了关键技术如RAG、Schema-aware prompt等的应用。最后,文章通过多个行业案例说明了DeepSeek的实际应用效果,显著降低了数据使用的门槛。 适合人群:从事数据分析、企业信息化建设的相关从业人员,尤其是对智能化数据处理感兴趣的业务和技术人员。 使用场景及目标:①帮助业务人员通过自然语言直接获取数据洞察;②降低传统BI工具的操作难度,提高数据分析效率;③为技术团队提供智能问数系统的架构设计和技术实现参考。 阅读建议:此资源不仅涵盖了DeepSeek的技术细节,还提供了丰富的实战案例,建议读者结合自身业务场景,重点关注DeepSeek在不同行业的应用方式及其带来的价值。对于希望深入了解技术实现的读者,可以进一步探索Prompt工程、RAG接入等方面的内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值