IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 时间复杂度O(nlogn)的排序算法 -> 正文阅读

[数据结构与算法]时间复杂度O(nlogn)的排序算法

时间复杂度O(nlogn)的排序算法有四种,分别是希尔排序,堆排序,快速排序和归并排序。这四个排序都非常重要。

希尔排序

希尔排序本质上是插入排序的优化,先对间隔较大的元素进行插入排序,完成宏观调控,然后逐步缩小间隔,最后一轮一定是间隔为 1 的排序,也就是插入排序。间隔在希尔排序中被称为「增量」,增量序列不同,希尔排序的效率也不同。

堆排序

堆排序的关键在于建堆,堆分为大顶堆和小顶堆,大顶堆中最大的元素在堆顶,小顶堆同理。

堆实际上是一颗完全二叉树,不过为了方便我们把它用数组的形式储存,储存的顺序为层次遍历的顺序。这种情况下,对于一个非叶子节点i,它的左子索引为2i+1,右子为2i+2。若数组长度为n,则堆中最后一个非叶子节点的索引为n/2+(n%2)-1.

假如现在有一个长度为n的无序数组,将他看做一颗完全二叉树,建大顶堆的过程:找到最后一个非叶子节点,比较它与它的两个子节点,若三者中最大的是某一子节点,则将他与父节点交换。然后向上遍历每一个非叶子节点,对他们都做一遍这样的比较交换操作,直到根节点。这样最后数组中的第一个就是最大的元素了。接下来把它与最后一个元素(n-1)交换,再对0到n-2的部分进行建堆,如此循环。

最小的 k 个数

public class Solution {
    public int[] GetLeastNumbers(int[] arr, int k) {
        if(k==arr.Length)
        return arr;
        int[] res=new int[k];
        for(int i=0;i<k;i++)
        {
            heap(arr,arr.Length-i-1);
            int t=arr[0];res[i]=t;
            arr[0]=arr[arr.Length-1-i];
            arr[arr.Length-1-i]=t;
        }
        return res;
    }
    public void heap(int[] arr,int len)
    {
        if(len==0)
        return;
        for(int i=len/2-1+(len%2);i>=0;i--)
        exchange(arr,i,len);
    }
    public void exchange(int[] arr,int i,int len)
    {
        if(i*2+2>len)
        {
            if(arr[i]>arr[2*i+1])
            {
                int t=arr[i];
                arr[i]=arr[2*i+1];
                arr[2*i+1]=t;
            }
        }
        else
        {
            if(arr[2*i+1]<=arr[2*i+2]&&arr[i]>arr[2*i+1])
            {
                int t=arr[i];
                arr[i]=arr[2*i+1];
                arr[2*i+1]=t;
            }
            else if(arr[2*i+2]<=arr[2*i+1]&&arr[i]>arr[2*i+2])
            {
                int t=arr[i];
                arr[i]=arr[2*i+2];
                arr[2*i+2]=t;
            }
        }
    }
}

快速排序

快速排序算法的基本步骤是:从数组中取出一个数,称之为基数(pivot),一般取第一个数作为基数,设两个指针L,R分别指向数组的最左和最右,R指针在大于L的情况下向左遍历寻找比基数小的数,找到以后将L位置赋值为这个数,L在小于R的情况下向右遍历寻找比基数大的数,找到以后将R位置赋值为这个数,重复上述循环,直到L=R。这时候将基数放在这个位置,对基数左边的部分和右边的部分分别进行上述循环。

快速排序实际上每次循环都把基数放在了最终排序里的位置。

归并排序

假设一个数组可以分为0~mid和mid+1~length-1两个有序的子数组,那么可以做如下排序,拷贝一个数组t,设两个指针i,j分别指向两个子数组的开头,比较两个指针指向的元素,将比较小的那个放入原数组,对应指针后移一位,继续比较,直到一个指针走到子数组的结尾。将剩下的一个子数组全部放入原数组。这样就完成了整个数组的排序。

通过上述的思想就可以完成一个递归的算法,因为当子数组细分到只有各元素时自然就是有序的了。

数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

?假设一个数组可以分为两个有序子数组AB,对它做归并排序,则如果将B数组的元素放入原数组,此时A中的为未放入的元素都比它大,这些元素的数目即为它构成的逆序对的数目。只要计算这些数目的和就可以了。

public class Solution {
    public int ReversePairs(int[] nums) {
        int[] temp=new int[nums.Length];
        return sort(nums,0,nums.Length-1,temp);
        
    }
    public int sort(int[] nums,int start,int end,int[] temp)
    {
        if(end-start<=0)
        return 0;
        int mid=(start+end)/2;
        int res=sort(nums,start,mid,temp)+sort(nums,mid+1,end,temp);
        for(int a=start;a<=end;a++)
        temp[a]=nums[a];
        int i=start,x=start,y=mid+1;
        while(x<=mid&&y<=end)
        {
            if(temp[x]<=temp[y])
            {
                nums[i]=temp[x];
                x++;
            }
            else
            {
                nums[i]=temp[y];
                res+=mid-x+1;
                y++;
            }
            i++;
        }
        if(x<=mid)
            for(;x<=mid;x++)
            nums[i++]=temp[x];
        else
            for(;y<=end;y++)
            nums[i++]=temp[y];
        return res;
    }
}

稳定性

希尔排序、堆排序、快速排序是不稳定的,归并排序是稳定的。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 23:27:37  更:2022-04-06 23:28:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:47:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码