插入,选择,堆,快速排序算法思想与复杂度

简介: 1.从第一个元素开始,将其视为已排序部分2.取出下一个元素,在已排序部分从后向前进行比较,找到合适的位置并插入3.重复上述步骤,直到所有元素都被插入到已排序部分。

目录


插入排序


思想


算法步骤


代码


复杂度


选择排序


思想


算法步骤


代码


复杂度


堆排序


思想


算法步骤


代码


复杂度


快速排序


思想


算法步骤


代码


复杂度


稳定性


插入排序

思想

插入排序是一种简单直观的排序算法。它的工作原理是将数组分为已排序和未排序两部分,然后依次将未排序元素插入到已排序部分的正确位置,直至整个数组排序完成。


算法步骤

1.从第一个元素开始,将其视为已排序部分


2.取出下一个元素,在已排序部分从后向前进行比较,找到合适的位置并插入


3.重复上述步骤,直到所有元素都被插入到已排序部分。

代码

    public static void insertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            int tmp = array[i];
            int j = i - 1;
            for (; j >= 0; j--) {
                if(tmp < array[j]) {
                    array[j+1] = array[j];
                }else {
                    break;
                }
            }
            array[j+1] = tmp;
        }
    }

复杂度

最坏情况时间复杂度:O(n^2) (数组完全逆序)

最好情况时间复杂度:O(n) (数组已经有序)

平均情况时间复杂度:O(n^2)

空间复杂度:O(1) (原地排序)

选择排序

思想

选择排序也是一种简单的排序算法。它的主要思想是每次从未排序部分选择最小(或最大)的元素,放到已排序部分的末尾,逐步形成有序序列。


算法步骤

1.从数组中找到最小元素,将其与第一个元素交换位置,将第一个元素视为已排序部分。


2.从剩余的未排序部分中找到最小元素,将其与第二个元素交换位置,将前两个元素视为已排序部分。


3.重复上述步骤,直到所有元素都排序完成。


代码

 

    public static void selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int min = i;
            for (int j = i+1; j < array.length; j++) {
                if (array[j] < array[min]) {
                    min = j;
                }
            }
            swap(array, i, min);
        }
    }
    private static void swap(int[] array, int i, int min) {
        int tmp = array[i];
        array[i] = array[min];
        array[min] = tmp;
    }

复杂度

最坏情况时间复杂度:O(n^2)

最好情况时间复杂度:O(n^2)

平均情况时间复杂度:O(n^2)

空间复杂度:O(1) (原地排序)

堆排序

思想

堆排序是一种高效的排序算法,利用了二叉堆的数据结构。它通过构建最大堆(升序排序时使用)或最小堆(降序排序时使用)来进行排序。


算法步骤

1.将输入数组构建成一个二叉堆。


2.不断从堆顶取出最大(或最小)元素,放入已排序部分的末尾,并调整堆保持其性质。


3.重复上述步骤,直到所有元素都被取出,形成有序序列。


代码

 

    public static void heapSort(int[] array) {
        createBigHeap(array);
        int end = array.length - 1;
        while (end > 0) {
            swap(array,0,end);
            siftDown(array,0,end);
            end--;
        }
    }
    private static void createBigHeap(int[] array) {
        for (int parent = (array.length-1-1) / 2; parent >= 0; parent--) {
            siftDown(array,parent,array.length);
        }
    }
    private static void siftDown(int[] array, int parent, int end) {
        int child = parent*2 + 1;
        while (child < end) {
            if(child+1 < end && array[child] < array[child+1]) {
                child++;
            }
            if (array[child] > array[parent]){
                swap(array,child,parent);
                parent = child;
                child = parent*2 + 1;
            }else {
                break;
            }
        }
    }

复杂度

最坏情况时间复杂度:O(n log n)

最好情况时间复杂度:O(n log n)

平均情况时间复杂度:O(n log n)

空间复杂度:O(1) (原地排序)

快速排序

思想

快速排序是一种常用且高效的排序算法,它采用了分治的思想。快速排序的核心在于选取一个基准元素,将数组分为左右两个子数组,使得左边的元素都小于等于基准,右边的元素都大于等于基准,然后对子数组递归地进行快速排序。


算法步骤

1.选择一个基准元素(通常为数组的第一个或最后一个元素)。


2.将数组分成两个子数组,使得左边子数组的元素都小于等于基准,右边子数组的元素都大 于等于基准。


3.对左右子数组递归地进行快速排序。


4.将左边子数组、基准元素和右边子数组合并成最终的有序数组。


代码

 

public static void quickSort(int[] array) {
        quick(array,0,array.length-1);
    }
    private static void quick(int[] array, int start, int end) {
        if(start >= end) {
            return;
        }
        int pivot = partition(array,start,end);
        quick(array,start,pivot-1);
        quick(array,pivot+1,end);
    }
    //挖坑法
    private static int partition(int[] array, int start, int end) {
        int key = array[start];
        while (start < end) {
            while (start < end && array[end] >= key) {
                end--;
            }
            array[start] = array[end];
            while (start < end && array[start+1] <= key) {
                start++;
            }
            array[end] = array[start];
        }
        array[start] = key;
        return start;
    }

复杂度

最坏情况时间复杂度:O(n^2) (基准选取不当导致)

最好情况时间复杂度:O(n log n) (每次都能将数组平衡地分割)

平均情况时间复杂度:O(n log n)

空间复杂度:O(log n) (递归调用栈的深度

稳定性

稳定的排序:插入排序,选择排序


不稳定排序:快速排序,堆排序


目录
相关文章
|
13天前
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
39 4
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
65 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
1月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
23 1
|
1月前
|
搜索推荐 Java Go
深入了解快速排序算法
深入了解快速排序算法
36 2
|
1月前
|
移动开发 算法 前端开发
前端常用算法全解:特征梳理、复杂度比较、分类解读与示例展示
前端常用算法全解:特征梳理、复杂度比较、分类解读与示例展示
22 0
|
2月前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
60 4
|
2月前
|
算法 程序员 Python
程序员必看!Python复杂度分析全攻略,让你的算法设计既快又省内存!
在编程领域,Python以简洁的语法和强大的库支持成为众多程序员的首选语言。然而,性能优化仍是挑战。本文将带你深入了解Python算法的复杂度分析,从时间与空间复杂度入手,分享四大最佳实践:选择合适算法、优化实现、利用Python特性减少空间消耗及定期评估调整,助你写出高效且节省内存的代码,轻松应对各种编程挑战。
41 1
|
1月前
|
存储 搜索推荐 算法
【排序算法(二)】——冒泡排序、快速排序和归并排序—>深层解析
【排序算法(二)】——冒泡排序、快速排序和归并排序—>深层解析
|
1月前
|
算法 Python
Python算法编程:冒泡排序、选择排序、快速排序
Python算法编程:冒泡排序、选择排序、快速排序