当前位置: 首页 > 编程日记 > 正文

算法系列15天速成——第二天 七大经典排序【中】

首先感谢朋友们对第一篇文章的鼎力支持,感动中....... 

今天说的是选择排序,包括“直接选择排序”和“堆排序”。

话说上次“冒泡排序”被快排虐了,而且“快排”赢得了内库的重用,众兄弟自然眼红,非要找快排一比高下。

这不今天就来了两兄弟找快排算账。

1.直接选择排序:

先上图:

说实话,直接选择排序最类似于人的本能思想,比如把大小不一的玩具让三岁小毛孩对大小排个序,

那小孩首先会在这么多玩具中找到最小的放在第一位,然后找到次小的放在第二位,以此类推。。。。。。

,小孩子多聪明啊,这么小就知道了直接选择排序。羡慕中........

对的,小孩子给我们上了一课,

第一步: 我们拿80作为参照物(base),在80后面找到一个最小数20,然后将80跟20交换。

第二步:  第一位数已经是最小数字了,然后我们推进一步在30后面找一位最小数,发现自己最小,不用交换。

第三步:........

最后我们排序完毕。大功告成。

既然是来挑战的,那就5局3胜制。

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6 using System.Diagnostics;
7
8 namespace SelectionSort
9 {
10 public class Program
11 {
12 static void Main(string[] args)
13 {
14 //5次比较
15 for (int i = 1; i <= 5; i++)
16 {
17 List<int> list = new List<int>();
18
19 //插入2w个随机数到数组中
20 for (int j = 0; j < 20000; j++)
21 {
22 Thread.Sleep(1);
23 list.Add(new Random((int)DateTime.Now.Ticks).Next(1000, 1000000));
24 }
25
26 Console.WriteLine("\n第" + i + "次比较:");
27
28 Stopwatch watch = new Stopwatch();
29
30 watch.Start();
31 var result = list.OrderBy(single => single).ToList();
32 watch.Stop();
33
34 Console.WriteLine("\n快速排序耗费时间:" + watch.ElapsedMilliseconds);
35 Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
36
37 watch.Start();
38 result = SelectionSort(list);
39 watch.Stop();
40
41 Console.WriteLine("\n直接选择排序耗费时间:" + watch.ElapsedMilliseconds);
42 Console.WriteLine("输出前十个数:" + string.Join(",", list.Take(10).ToList()));
43
44 }
45 }
46
47 //选择排序
48 static List<int> SelectionSort(List<int> list)
49 {
50 //要遍历的次数
51 for (int i = 0; i < list.Count - 1; i++)
52 {
53 //假设tempIndex的下标的值最小
54 int tempIndex = i;
55
56 for (int j = i + 1; j < list.Count; j++)
57 {
58 //如果tempIndex下标的值大于j下标的值,则记录较小值下标j
59 if (list[tempIndex] > list[j])
60 tempIndex = j;
61 }
62
63 //最后将假想最小值跟真的最小值进行交换
64 var tempData = list[tempIndex];
65 list[tempIndex] = list[i];
66 list[i] = tempData;
67 }
68 return list;
69 }
70 }
71 }

比赛结果公布:

堆排序:

要知道堆排序,首先要了解一下二叉树的模型。

下图就是一颗二叉树,具体的情况我后续会分享的。

那么堆排序中有两种情况(看上图理解):

大根堆:  就是说父节点要比左右孩子都要大。

小根堆:  就是说父节点要比左右孩子都要小。

那么要实现堆排序,必须要做两件事情:

第一:构建大根堆。

首先上图:

首先这是一个无序的堆,那么我们怎样才能构建大根堆呢?

第一步: 首先我们发现,这个堆中有2个父节点(2,,3);

第二步: 比较2这个父节点的两个孩子(4,5),发现5大。

第三步: 然后将较大的右孩子(5)跟父节点(2)进行交换,至此3的左孩子堆构建完毕,

如图:

第四步: 比较第二个父节点(3)下面的左右孩子(5,1),发现左孩子5大。

第五步: 然后父节点(3)与左孩子(5)进行交换,注意,交换后,堆可能会遭到破坏,

必须按照以上的步骤一,步骤二,步骤三进行重新构造堆。

最后构造的堆如下:

第二:输出大根堆。

至此,我们把大根堆构造出来了,那怎么输出呢?我们做大根堆的目的就是要找出最大值,

那么我们将堆顶(5)与堆尾(2)进行交换,然后将(5)剔除根堆,由于堆顶现在是(2),

所以破坏了根堆,必须重新构造,构造完之后又会出现最大值,再次交换和剔除,最后也就是俺们

要的效果了,

发现自己兄弟被别人狂殴,,堆排序再也坐不住了,决定要和快排干一场。

同样,快排也不甘示弱,谁怕谁?

  1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6 using System.Diagnostics;
7
8 namespace HeapSort
9 {
10 public class Program
11 {
12 static void Main(string[] args)
13 {
14 //5次比较
15 for (int j = 1; j <= 5; j++)
16 {
17 List<int> list = new List<int>();
18
19 //插入2w个数字
20 for (int i = 0; i < 20000; i++)
21 {
22 Thread.Sleep(1);
23 list.Add(new Random((int)DateTime.Now.Ticks).Next(1000, 100000));
24 }
25
26 Console.WriteLine("\n第" + j + "次比较:");
27
28 Stopwatch watch = new Stopwatch();
29 watch.Start();
30 var result = list.OrderBy(single => single).ToList();
31 watch.Stop();
32 Console.WriteLine("\n快速排序耗费时间:" + watch.ElapsedMilliseconds);
33 Console.WriteLine("输出前十个数" + string.Join(",", result.Take(10).ToList()));
34
35 watch = new Stopwatch();
36 watch.Start();
37 HeapSort(list);
38 watch.Stop();
39 Console.WriteLine("\n堆排序耗费时间:" + watch.ElapsedMilliseconds);
40 Console.WriteLine("输出前十个数" + string.Join(",", list.Take(10).ToList()));
41 }
42
43 }
44
45 ///<summary>
46 /// 构建堆
47 ///</summary>
48 ///<param name="list">待排序的集合</param>
49 ///<param name="parent">父节点</param>
50 ///<param name="length">输出根堆时剔除最大值使用</param>
51 static void HeapAdjust(List<int> list, int parent, int length)
52 {
53 //temp保存当前父节点
54 int temp = list[parent];
55
56 //得到左孩子(这可是二叉树的定义,大家看图也可知道)
57 int child = 2 * parent + 1;
58
59 while (child < length)
60 {
61 //如果parent有右孩子,则要判断左孩子是否小于右孩子
62 if (child + 1 < length && list[child] < list[child + 1])
63 child++;
64
65 //父亲节点大于子节点,就不用做交换
66 if (temp >= list[child])
67 break;
68
69 //将较大子节点的值赋给父亲节点
70 list[parent] = list[child];
71
72 //然后将子节点做为父亲节点,已防止是否破坏根堆时重新构造
73 parent = child;
74
75 //找到该父亲节点较小的左孩子节点
76 child = 2 * parent + 1;
77 }
78 //最后将temp值赋给较大的子节点,以形成两值交换
79 list[parent] = temp;
80 }
81
82 ///<summary>
83 /// 堆排序
84 ///</summary>
85 ///<param name="list"></param>
86 public static void HeapSort(List<int> list)
87 {
88 //list.Count/2-1:就是堆中父节点的个数
89 for (int i = list.Count / 2 - 1; i >= 0; i--)
90 {
91 HeapAdjust(list, i, list.Count);
92 }
93
94 //最后输出堆元素
95 for (int i = list.Count - 1; i > 0; i--)
96 {
97 //堆顶与当前堆的第i个元素进行值对调
98 int temp = list[0];
99 list[0] = list[i];
100 list[i] = temp;
101
102 //因为两值交换,可能破坏根堆,所以必须重新构造
103 HeapAdjust(list, 0, i);
104 }
105 }
106 }
107 }

结果公布:

堆排序此时心里很尴尬,双双被KO,心里想,一定要捞回面子,一定要赢,

于是堆排序提出了求“前K大问题”。(就是在海量数据中找出前几大的数据),

快排一口答应,小意思,没问题。

双方商定,在2w随机数中找出前10大的数:

  1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6 using System.Diagnostics;
7
8 namespace QuickSort
9 {
10 public class Program
11 {
12 static void Main(string[] args)
13 {
14 //5此比较
15 for (int j = 1; j <= 5; j++)
16 {
17 List<int> list = new List<int>();
18
19 for (int i = 0; i < 20000; i++)
20 {
21 Thread.Sleep(1);
22 list.Add(new Random((int)DateTime.Now.Ticks).Next(1000, 100000));
23 }
24
25 Console.WriteLine("\n第" + j + "次比较:");
26
27 Stopwatch watch = new Stopwatch();
28 watch.Start();
29 var result = list.OrderByDescending(single => single).Take(10).ToList();
30 watch.Stop();
31 Console.WriteLine("\n快速排序求前K大耗费时间:" + watch.ElapsedMilliseconds);
32 Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
33
34 watch = new Stopwatch();
35 watch.Start();
36 result = HeapSort(list, 10);
37 watch.Stop();
38 Console.WriteLine("\n堆排序求前K大耗费时间:" + watch.ElapsedMilliseconds);
39 Console.WriteLine("输出前十个数:" + string.Join(",", list.Take(10).ToList()));
40 }
41
42 }
43
44 ///<summary>
45 /// 构建堆
46 ///</summary>
47 ///<param name="list">待排序的集合</param>
48 ///<param name="parent">父节点</param>
49 ///<param name="length">输出根堆时剔除最大值使用</param>
50 static void HeapAdjust(List<int> list, int parent, int length)
51 {
52 //temp保存当前父节点
53 int temp = list[parent];
54
55 //得到左孩子(这可是二叉树的定义哇)
56 int child = 2 * parent + 1;
57
58 while (child < length)
59 {
60 //如果parent有右孩子,则要判断左孩子是否小于右孩子
61 if (child + 1 < length && list[child] < list[child + 1])
62 child++;
63
64 //父节点大于子节点,不用做交换
65 if (temp >= list[child])
66 break;
67
68 //将较大子节点的值赋给父亲节点
69 list[parent] = list[child];
70
71 //然后将子节点做为父亲节点,已防止是否破坏根堆时重新构造
72 parent = child;
73
74 //找到该父节点左孩子节点
75 child = 2 * parent + 1;
76 }
77 //最后将temp值赋给较大的子节点,以形成两值交换
78 list[parent] = temp;
79 }
80
81 ///<summary>
82 /// 堆排序
83 ///</summary>
84 ///<param name="list">待排序的集合</param>
85 ///<param name="top">前K大</param>
86 ///<returns></returns>
87 public static List<int> HeapSort(List<int> list, int top)
88 {
89 List<int> topNode = new List<int>();
90
91 //list.Count/2-1:就是堆中非叶子节点的个数
92 for (int i = list.Count / 2 - 1; i >= 0; i--)
93 {
94 HeapAdjust(list, i, list.Count);
95 }
96
97 //最后输出堆元素(求前K大)
98 for (int i = list.Count - 1; i >= list.Count - top; i--)
99 {
100 //堆顶与当前堆的第i个元素进行值对调
101 int temp = list[0];
102 list[0] = list[i];
103 list[i] = temp;
104
105 //最大值加入集合
106 topNode.Add(temp);
107
108 //因为顺序被打乱,必须重新构造堆
109 HeapAdjust(list, 0, i);
110 }
111 return topNode;
112 }
113 }
114 }

求前K大的输出结果:

最后堆排序赶紧拉着直接选择排序一路小跑了,因为求前K大问题已经不是他原本来的目的。

ps: 直接选择排序的时间复杂度为:O(n^2)

堆排序的时间复杂度:O(NlogN)

相关文章:

如何构建优质的推荐系统服务?| 技术头条

作者丨gongyouliu来源 | 大数据与人工智能&#xff08;ID:ai-big-data&#xff09;任何一个优质的软件服务都必须考虑高性能、高可用(HighAvailability)、可伸缩、可拓展、安全性等5大核心要素&#xff0c;推荐系统也不例外。所以&#xff0c;我们会围绕这5个点来说明&#xff…

DispatcherServlet之HandlerAdapter的handle

2019独角兽企业重金招聘Python工程师标准>>> 注&#xff1a;SpringFramework的版本是4.3.x。 1.DispatcherServlet的doService方法时序图 图1 DispatcherServlet的doService方法时序图 2.AnnotationMethodHandlerAdapter的handle方法时序图 图2的原图在Gith…

【C++】C++11 STL算法(九):番外篇

1、如果获取指针或迭代器指向的类型 详见&#xff1a;C 11&#xff1a;如何获取一个指针或迭代器指向的类型&#xff1f; decltype(*std::declval<Pointer>())decltype&#xff1a;c11关键字&#xff0c;类型推导。详见&#xff1a;【C】C11新增关键字详解 std::declva…

IBM Tivoli Netview在企业网络管理中的实践(附视频)

今天我为大家介绍的一款高端网管软件名叫IBM Tivoli NetView&#xff0c;他主要关注是IBM整理解决方案的用户&#xff0c;分为Unix平台和Windwos平台两种&#xff0c;这里视频演示的是基于Windows 2003 server下的IBM Tivoli NetView 6.1在企业中的部署应用&#xff0c;可以为大…

【C++】C++11 STL算法(十):使用STL实现排序算法

一、快速排序 1、适用于c11版本 template <class ForwardIt> void quicksort(ForwardIt first, ForwardIt last) {if(first last) return;auto pivot *std::next(first, std::distance(first,last)/2);ForwardIt middle1 std::partition(first, last, [pivot](con…

“你行你上”:有本事跟OpenAI Five打一把DOTA?| 极客头条

整理 | 一一出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;你们不是嫌弃世界冠军 OG 团队实力太水吗&#xff1f;“你行你上”的机会来了。4 月 14 日凌晨&#xff0c;OpenAI Five 以 2:0 击败了 DOTA 世界冠军团队 OG 引发热议。比赛当天&#xff0c;OpenAI 也宣布…

Java学习笔记二十五:Java面向对象的三大特性之多态

Java面向对象的三大特性之多态 一&#xff1a;什么是多态&#xff1b; 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口&#xff0c;使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现。 现实中&#xff0c;比如我们按下 F1 键这个动作&am…

省钱之道--图解域域树域林根域的含义

省钱之道--图解域域树域林根域的含义 标签&#xff1a;域 域林 图解域域树域林根域的含义 域树 根域原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://angerfire.blog.51cto.com/198455/1…

AI算法在FPGA芯片上还有这种操作?| 技术头条

作者 | 杨付收出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;碾压与崛起AI算法的崛起并非一帆风顺的&#xff0c;现在的主流的NN类的卷积神经网络已经是第二波浪潮了&#xff0c;早在上个世纪80年代&#xff0c;源于仿生学&#xff0c;后又发展于概率学的早期AI算…

[Doctrine Migrations] 数据库迁移组件的深入解析三:自定义数据字段类型

自定义type 根据官方文档&#xff0c;新建TinyIntType类&#xff0c;集成Type&#xff0c;并重写getName&#xff0c;getSqlDeclaration&#xff0c;convertToPHPValue&#xff0c;getBindingType等方法。 TinyIntType.php完整代码&#xff1a; <?php namespace db\types; …

【网络编程】同步IO、异步IO、阻塞IO、非阻塞IO

IO分两阶段&#xff1a; 1.数据准备阶段&#xff1a;在该阶段&#xff0c;根据是否等待数据准备&#xff0c;将IO分成阻塞和非阻塞&#xff1b; 2.内核空间复制回用户进程缓冲区阶段&#xff1a;在该阶段&#xff0c;只要程序需要等待复制完成&#xff0c;才能往下运行&#xf…

PowerDesigner 使用的一些技巧(转)

-> Generate Database &#xff0c;在弹出的 Database Generation 对话框中选择脚本存取路径及脚本文件名称 3、点击确定后生成数据库建库脚本(*.sql) 二、生成脚本时报错&#xff1a; Column Code maxinum lenght 原因&#xff1a;字段超过15字符就发生错误&…

【网络编程】epoll 笔记

一、最大连接数 1、select select在单进程中最多同时监听1024个fd&#xff1b;要想实现百万并发需要一千个进程&#xff0c;并且性能会很差、内存消耗巨大。所以select只适用于连接数在一千个以下的场景。 2、epoll epoll本身不限制连接数&#xff0c;但是连接数会受到系统…

交通图网络太大太复杂,没法处理?DMVST-Net巧妙处理

参加「CTA 核心技术及应用峰会」&#xff0c;请扫码报名 ↑↑↑作者 | Huaxiu Yao, Fei Wu, Jintao Ke, Xianfeng Tang等译者 | 一步一步望着天上星编辑 | Jane出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;【导语】自 2018 年 6 月 DeepMind 发表论文“…

小程序这件事 撸起袖子加油干

写在前面的话&#xff1a; 初次接触小程序&#xff0c;便被它开发的简易与便捷所吸引。总按耐不住对未知的探索欲望&#xff0c;于是乎撸起袖子来干一个吧。附&#xff1a;小程序开发文档 项目介绍 艺龙酒店小程序实践 使用<swiper>标签实现网页轮播图的效果&#xff0c;…

mutt使用小技巧 指定发件人 添加附件

经常我们需要从linux服务器上直接发送一些邮件到自己&#xff0c;或者用户的邮箱里&#xff0c;mail命令固然重要&#xff0c;但是缺点是不能方便的进行插入附件。这里选择使用mutt&#xff0c;方便又好用。 实例&#xff1a; echo "邮件内容" | mutt -e "my_hd…

恶犬秒变萌汪:东京大学开源“治愈系”GAN图片拼贴工具 | 技术头条

参加「CTA 核心技术及应用峰会」&#xff0c;请扫码报名 ↑↑↑译者 | linstancy责编 | 琥珀出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;教新手画画&#xff1f;字体风格迁移&#xff1f;换明星“假脸”&#xff1f;毫无疑问&#xff0c;在图像生成中…

【视频】视频传输协议:RTSP、RTP、RTCP、RTMP、HTTP

一、RTSP、RTP、RTCP RTSP、RTP、RTCP是一组协议,其中RTSP在应用层、RTP和RTCP在传输层。RTP用于传输流媒体数据,而RTCP对RTP进行控制、同步。 二、RTSP、RTMP、HTTP 1、共同点 RTSP、RTMP、HTTP都是用在应用层。理论上这三种协议都可以做直播和点播,但直播一般用RTSP和…

ActiveMQ5.14.5配置参数详解

Activemq-.xml1.加载properties配置参数。下面加载是访问broker的身份信息&#xff0c;即用户名和密码 <bean class"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name"locations"><value>file:…

正则表达式实现最小匹配

正则表达式默认情况下实现的是最大化匹配&#xff0c;这在有些情况下是非常不愿意出现的&#xff0c;比如下面这段代码&#xff1a; # starting IndiaInventoryAPP.exe" ~~DisplayVariableValues "parameterGroup,mailRecipients,ModuleArgs"~DisplayVariableVa…

Azure系列2.1.15 —— SharedAccessBlobPolicy

&#xff08;小弟自学Azure&#xff0c;文中有不正确之处&#xff0c;请路过各位大神指正。&#xff09; 网上azure的资料较少&#xff0c;尤其是API&#xff0c;全是英文的&#xff0c;中文资料更是少之又少。这次由于公司项目需要使用Azure&#xff0c;所以对Azure的一些学习…

Facebook AI新架构:全景FPN,同时完成图像实例与语义分割 | 极客头条

参加「CTA 核心技术及应用峰会」&#xff0c;请扫码报名 ↑↑↑整理 | 刘旭坤、Jane出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;实例分割和语义分割长期以来都是运用不同的神经网络架构来完成的&#xff0c;虽然最近出现了将语义和实例分割进行结合的…

【经验】向word中插入格式化的代码块

参考博客&#xff1a;如何在word中插入代码块 1、打开http://www.planetb.ca/syntax-highlight-word网站 语法高亮显示Word文档中的代码 2、将你的代码复制进去&#xff0c;选择编译语言&#xff0c;点击“Show Highlighted” 3、复制格式化后的代码 4、直接在word中粘贴代…

用路由器限制局域网的带宽流量

有时在上班的时候&#xff0c;带宽并不是很高&#xff0c;但又因个别人过量占用带宽导致其它人正常上网的速度都很慢&#xff0c;正常的工作都无法开展&#xff0c;所以对局域网内主机带宽流量的管理就必不可少了。 公司并不是很多的电脑&#xff0c;且预算不是很多的&…

Lumen / Laravel 5.5 使用网易邮箱 SMTP 发送邮件

2019独角兽企业重金招聘Python工程师标准>>> Laravel 是目前最流行的PHP框架&#xff0c;而Lumen 是 Laravel 的精简版&#xff0c;主要用于接口开发。 Laravel 邮件发送服务基于 Symfony 组件 Swift Mailer。 本文记录了在 Lumen / Laravel 5 环境中&#xff0c;使…

终于有人把数据、信息、算法、统计、概率和数据挖掘都讲明白了!

插画设计&#xff1a;万娟01什么是数据数据是什么&#xff1f;这几乎成为一个我们熟视无睹的问题。有不少朋友脑子里可能会直接冒出一个词“数字”——“数字就是数据”&#xff0c;我相信会有一些朋友会斩钉截铁地这么告诉我。一些朋友会在稍作思考后回答“数字和字符、字母&a…

【经验】配置Anaconda源

配置清华源&#xff1a; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/

oracle update批量修改sql语句编写

update Suncco_Tz_Tbl_Task t set t.taskname网络部储备&#xff08;室分&#xff09;土建 , t.tasktype交换-交换主设备-电路域设备 , t.taskbyarea思明 , t.addresscoding2422BG00003735 update SUNCCO_TZ_TBL_TASK task set task.taskname11 , task.type33 where task.TA…

深入卷积神经网络背后的数学原理 | 技术头条

参加「CTA 核心技术及应用峰会」&#xff0c;请扫码报名 ↑↑↑作者 | Piotr Skalski译者 | Monanfei编辑 | 十月Rachel、Jane出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;【导读】在计算机神经视觉技术的发展过程中&#xff0c;卷积神经网络成为了其中…

【AI】在win10上安装TensorFlow2,安装成功,但是import tensorflow时报错:pywrap_tensorflow.py“, line 58

目录一、问题描述二、原因分析三、处理过程四、解决方法五、安装2.1和2.0命令的不同点1、TensorFlow2.02、TensorFlow2.1六、使用TenforFlow2.0-GPU时&#xff0c;报错:cudart64_100.dll not found1、错误信息如下2、原因分析3、解决方法七、测试TensorFlow是否支持GPU1、测试对…