算法学习笔记——排序问题

学习笔记,仅做记录,如有错漏,望指出,谢谢。


1.简单选择排序(选择类排序)

使用方法:蛮力法
平均时间复杂度为: O(n2) ,最坏时间复杂度为 O(n2) ,最好时间复杂度为 O(n) ,稳定(排序算法稳定性详见百度百科)
空间复杂度为 O(1)

i=0n2j=i+1n1=i=0n2(ni1)=n(n1)2=O(n2)

package com.viper.sort;

public class SelectSort {

    public static void sort(int array[]) {
        for (int i = 0; i < array.length; i++) {
            int index = i;
            for (int j = i + 1; j < array.length; j++) {
                // 查找无序区最小的记录
                if (array[j] < array[index])
                    index = j;
            }
            if (index != i) {
                // 将无序区最小的记录添加到有序区末尾
                int temp = array[i];
                array[i] = array[index];
                array[index] = temp;
            }
        }
    }
}

2.冒泡排序(交换类排序)

使用方法:蛮力法
平均时间复杂度为: O(n2) ,最坏时间复杂度为 O(n2) ,最好时间复杂度为 O(n) ,空间复杂度为 O(1) ,稳定
首先将元素分为有序区和无序区,初始时,有序区为零。遍历比较无序区中的相邻元素,将较大元素后移,并记录每次最后发生交换的位置,以确定有序区和无序区。重复遍历比较无序区中相邻元素直至无序区为零。

package com.viper.sort;

public class BubbleSort {

    public static void sort(int[] array) {
        int bound, exchange = array.length - 1;
        while (exchange != 0) {
            bound = exchange;
            exchange = 0;//重置为零,若未交换则排序完毕
            for (int i = 0; i < bound; i++) {
                if (array[i] > array[i + 1]) {
                    int temp = array[i];
                    array[i] = array[i + 1];
                    array[i + 1] = temp;
                    exchange = i;//记录每次交换的位置
                }
            }
        }
    }
}

3.快速排序(交换类排序)

使用方法:分治法
平均时间复杂度为 O(nlog2n) 最坏时间复杂度为 O(n2) ,最好时间复杂度为 O(nlog2n) ,空间复杂度为 O(nlog2n) ,不稳定
对待排序元素进行扫描,确定中间的轴值,以轴值为划分,一侧元素均小于轴值,一侧元素均大于轴值。对以轴值划分的区域递归排序。

package com.viper.sort;

public class QuickSort {

    public static void sort(int[] array) {
        quickSort(array, 0, array.length - 1);
    }

    /**
     * 快速排序
     */
    private static void quickSort(int[] array, int first, int end) {
        int pivot;
        if (first < end) {
            pivot = partition(array, first, end);
            quickSort(array, first, pivot - 1);
            quickSort(array, pivot + 1, end);
        }
    }

    /**
     * 扫描并划分待排序元素,返回轴值
     */
    private static int partition(int array[], int first, int end) {
        int i = first, j = end;
        while (i < j) {// i==j停止,确定轴值
            while (i < j && array[i] <= array[j]) {
                j--;
            }
            if (i < j) {
                swap(array[i], array[j]);
                i++;
            }
            while (i < j && array[i] <= array[j]) {
                i++;
            }
            if (i < j) {
                swap(array[i], array[j]);
                j--;
            }
        }
        return i;
    }

    private static void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }
}

5.归并排序

使用方法:分治法
时间复杂度为 O(nlog2n) (执行一次合并算法的时间复杂度为 O(n) ),空间复杂度为 O(n) ,稳定
对待排序序列进行划分,直至序列有序(即序列长度为1),对有序子序列进行合并,直至排序完成

package com.viper.sort;

public class MergeSort {

    public static void sort(int[] array) {
        mergeSort(array, 0, array.length - 1);
    }

    private static void mergeSort(int[] array, int start, int end) {
        if (start == end) {
            return;
        } else {
            int mid = (start + end) / 2;
            //递归划分
            mergeSort(array, start, mid);
            mergeSort(array, mid + 1, end);
            //合并子序列
            merge(array, start, mid, end);
        }
    }

    private static void merge(int[] array, int start, int mid, int end) {
        int[] tempArr = new int[array.length];
        int i = start, j = mid + 1, k = start;
        while (i < mid && j < end) {
            if (array[i] <= array[j]) {
                tempArr[k++] = array[i++];
            } else {
                tempArr[k++] = array[j++];
            }
        }
        //将未处理完的序列依次放入结果中
        while (i <= mid) {
            tempArr[k++] = array[i++];
        }
        while (j <= end) {
            tempArr[k++] = array[j++];
        }
        //将已排序序列复制回原序列
        while(start <= k) {
            array[k] = tempArr[k--];
        }
    }
}

4.直接插入排序(插入类排序)

使用方法:减治法
平均时间复杂度为 O(n2) ,最坏时间复杂度为 O(n2) ,最好时间复杂度为 O(n) ,空间复杂度为 O(1) ,稳定
将待排序序列划分为有序区和无序区,初始有序区元素个数为零,取无序区第一个元素,与有序区元素逐个毕竟,插入到合适位置,直至无序区元素个数为零

package com.viper.sort;

public class InsertSort {
    public static void sort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            int j, temp = array[i];
            for (j = i - 1; j > 0 && temp < array[j]; j--) {
                array[j + 1] = array[j];
            }
            array[j + 1] = temp;
        }
    }
}

6.堆排序(选择类排序)

使用方法:减治法
堆(heap)是具有下列性质的完全二叉树:每个结点的值都小于(大于)或等于其左右孩子结点的值
时间复杂度为 O(nlog2n) ,空间复杂度为 O(1) ,不稳定

package com.viper.sort;

public class HeapSort {

    public static void sort(int[] array) {
        int i, temp;
        for (i = array.length - 1; i >= 0; i--) {
            siftHeap(array, i, array.length);// 初始建堆,从最后一个分支开始
        }

        for (i = 1; i < array.length; i++) {
            temp = array[0];
            array[0] = array[array.length - i];
            array[array.length - i] = temp;
            siftHeap(array, 0, array.length - i);//调整当前根结点
        }
    }

    /**
     * 筛选法调整堆
     */
    private static void siftHeap(int[] array, int k, int n) {
        int i = k, j = 2 * i + 1, temp;// i根结点,j指向左孩子
        while (j < n) {// 判断是否为叶子结点
            if (j < n - 1 && array[j] < array[j + 1]) {
                j++;
            }
            if (array[i] > array[j]) {// 根结点值较大
                break;
            } else {// 交换根结点与较大孩子结点
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}

7.希尔排序(插入类排序)

平均时间复杂度为 O(nlog2n) ,最坏时间复杂度为 O(nlog2n) ,空间复杂度为O(1),希尔排序不稳定

package com.viper.sort;

public class ShellSort {

    public static void sort(int[] array) {
        for (int step = 5;step > 0; step--) {//此处step默认为5
            for (int i = 0; i < step; i++) {// 每一组
                for (int j = i + step; j < array.length; j += step) {// 插入排序
                    int k, temp = array[j];
                    for (k = j - step; k >= 0 && temp < array[k]; k -= step) {
                        array[k + step] = array[k];
                    }
                    array[j + step] = temp;
                }
            }
        }
    }
}

8.基数排序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
cda备考学习学习笔记——基础知识篇(二)主要涉及了计算机科学与技术领域的基本概念和知识。 首先,它介绍了计算机网络的基础知识。网络是将多台计算机通过通信链路连接起来,使它们能够相互通信和共享资源的系统。笔记中详细介绍了网络的组成、拓扑结构和通信协议等重要内容。 其次,笔记还解释了计算机系统的基本组成。计算机系统由硬件和软件两部分组成,其中硬件包括中央处理器、存储器、输入输出设备等,而软件则分为系统软件和应用软件。笔记详细介绍了各种硬件和软件的功能和作用。 此外,笔记还对数据库管理系统进行了介绍。数据库管理系统是一种用于管理和组织数据的软件系统,它能够实现数据的存储、检索和更新等操作。笔记中详细介绍了数据库的概念、结构和操作等内容。 最后,笔记还包括了算法和数据结构的基础知识。算法是解决问题的一系列步骤和规则,而数据结构则是组织和存储数据的方式。笔记中介绍了常用的算法和数据结构,如排序算法、树和图等。 总之,通过学习CDA备考学习笔记中的基础知识篇(二),我们能够更好地理解计算机网络、计算机系统、数据库管理系统以及算法和数据结构等相关概念和知识。这些基础知识对于我们深入研究计算机科学与技术领域是非常重要的,也为我们日后的学习和工作奠定了坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值