P1177 【模板】快速排序

不用说,连题目上都标了是一道模板,那今天就来对能用到的许多排序方式进行一个总结:

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。(稳定不稳定最后再讲)

这是选择排序的思想:每一趟在n-i+1(i=1,2,3…,n-1)个记录中选取关键字最小的记录与第i个记录交换,并作为有序序列中的第i个记录。

例如:
待排序列: 43,65,4,23,6,98,2,65,7,79
第一趟: 2,65,4,23,6,98,43,65,7,79
第二趟: 2,4,65,23,6,98,43,65,7,79
第三趟: 2,4,6,23,65,98,43,65,7,79
第四趟: 2,4,6,7,43,65,98,65,23,79
第五趟: 2,4,6,7,23,65,98,65,43,79
第六趟: 2,4,6,7,23,43,98,65,65,79
第七趟: 2,4,6,7,23,43,65,98,65,79
第八趟: 2,4,6,7,23,43,65,65,98,79
第九趟: 2,4,6,7,23,43,65,65,79,98

贴个代码:

#include <iostream>
using namespace std;
void SelectSort(int a[], int n) //选择排序
{
int mix, temp;
for (int i = ; i < n - ; i++) //每次循环数组,找出最小的元素,放在前面,前面的即为排序好的
{
mix = i; //假设最小元素的下标 for(int j=i+1;j<n;j++)
//将上面假设的最小元素与数组比较,交换出最小的元素的下标
if (a[j] < a[mix])
mix = j; //若数组中真的有比假设的元素还小,就交换
if (i != mix)
{
temp = a[i];
a[i] = a[mix];
a[mix] = temp;
}
}
}
int main()
{
int a[] = {, , , , , , , , , };
SelectSort(a, );
for (int i = ; i < ; i++)
cout << a[i] << " ";
cout << endl;
return ;
}

很明显,我们用到了两个嵌套的循环,所以时间复杂度就是o(n^2)的

然鹅。。。。正常人都会觉得这算法太慢了吧!!!!!!

所以我们来讲个好一点的;

冒泡排序(也是我比较喜欢的一种)

具体思路是什么呢:

冒泡排序的基本思想为:
一趟冒泡排序的过程为:首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则将两个记录交换之,然后比较第二个记录的关键字和第三个记录的关键字,依次类推,直至第n-1个记录和第n个记录的关键字进行过比较为止;
在冒泡排序的过程中,关键字较小的记录好比肥宅快乐水(雾)的气泡逐趟向上漂浮,而关键字较大的记录好比石头往下沉,每一趟有一块“最大”的石头沉到水底。

还是上面那个数
待排序列:43, 65, 4, 23, 6, 98, 2, 65, 7, 79
第一趟: 43, 4,23,6,65,2,65,7,79,98
第二趟: 4,23,6,43,2,65,7,65,79,98
第三趟: 4,6,23,2,43,7,65,65,79,98
第四趟: 4,6,2,23,7,43,65,65,79,98
第五趟: 4,2,6,7,23,43,65,65,79,98
第六趟: 2,4,6,7,23,43,65,65,79,98

冒泡排序的时间复杂度为:O(n^2),空间复杂度为O(1)

冒泡排序是稳定的;

好吧其实这俩货时间复杂度是一样的,但是我还是喜欢用冒泡QAQ

贴一下代码吧

#include <iostream>
#include <algorithm>
using namespace std;
void bubleSort(int a[], int n) //冒泡排序
{
//运用两个for循环,每次取出一个元素跟数组的其它元素比较,将最大的元素排到最后
for (int i = ; i < n - ; i++)
{ //外循环一次,就排好一个数,并放在后面,所以比较前面n-i-1个元素即可
for (int j = ; j < n - i - ; j++)
{
if (a[j] > a[j + ])
{
swap(a[j],a[j+]);//swap其实和之前那个temp的作用是一样的,就是交换一下数字而已
}
}
}
}
int main()
{
int a[] = {, , , , , , , , , };
bubleSort(a, );
for (int i = ; i < ; i++)
cout << a[i] << " ";
cout << endl;
return ;
}

冒泡排序其实还有一个挺重要的用处,就是找一堆数里头的最大数和最小数,其实就是用的冒泡的方法

for(int i=;i<=n;i++)
{
if(a[i]>Max)
Max=a[i];
}

还有一个很重要的排序方式

快速排序

一听就很快啊有没有(雾)

快速排序的思想是找一个基准数,比基准数小的扔到左边去,大的扔到右边去(升序排列时)

听起来挺简单的吧,,,代码实现可能有一点点复杂,慢慢看

代码如下

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
int findPos(int a[], int low, int high)
{
//将小于t的元素赶到t的左边,大于t的元素赶到t的右边
int t = a[low];
while (low < high)
{
while (low < high && a[high] >= t)
high--;
a[low] = a[high];
while (low < high && a[low] <= t)
low++;
a[high] = a[low];
}
a[low] = t; //返回此时t在数组中的位置
return low;
} //在数组中找一个元素,对于大于该元素和小于该元素的两个数组进行再排序,
//再对两个数组分为4个数组,再排序,直到最后每组只剩下一个元素为止
void quickSort(int a[], int low, int high) //快速排序
{
if (low > high)
return;
int pos = findPos(a, low, high);
quickSort(a, low, pos - );
quickSort(a, pos + , high);
}
int main()
{
int, n, a[];
scanf("%d", &n);
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]);
quickSort(a, , sizeof(a));
for (int i = ; i < ; i++)
cout << a[i] << " ";
cout << endl;
return ;
}

我们再来看看归并排序这个东西

归并排序(最不常用但是是实打实的快的算法)

将两个的有序数列合并成一个有序数列,我们称之为"归并"。
归并排序(Merge Sort)就是利用归并思想对数列进行排序。根据具体的实现,归并排序包括"从上往下"和"从下往上"2种方式。

基本思想:先将整个数组分成两个部分,分别将两个部分排好序,然后将两个排好序的数组O(n)合并成一个数组。
我们将问题分为两个阶段:分、治

对于每个长度> 1的区间,拆成两个[l, mid]区间
和[mid + 1, r]区间
直接递归下去

这样的话就可以一直递归直到只剩下一个数的时候,就分完了

我们认为在处理区间[l,r]时,已经有[l,mid]和[mid+1,r]内分别有序,这一次的操作就是合并两个有序序列,成为一个新的长有序序列。
用两个指针分别指向左右分别走到哪了即可

举一个例子吧,比如我们要合并这两个数组(模拟一下合并过程)

135

246

显然你肯定不能把246直接接到135后面对吧,这个时候我们建两个指针S1=1和S2=1(我的习惯是下标从1开始)

然后干这样一件事先比较a[s1]和b[s2]的大小,这里1更小一点,

所以

c[i]=b[s2];

S2++;

这里其实就是用两个指针分别从要合并的两个数组的头元素指起,如果元素被合并,那么就指针++,直到两个数组的指针都指完为止,就是这一块

算法的时间复杂度就是O(nlogN)

然后再看看堆排()

堆的讲解点这里QWQ

堆排吧,其实就是利用一个大根堆或者是小根堆来对一组数据进行合并和动态维护其顺序。

其代码本身并没有与堆的板子有太多差别,而是完全按照加入元素弹出元素那些函数来维护的,改一改就能交啦

自己黈自己(QWQ还是gh神仙给我纠正手写堆)

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdio>
using namespace std;
int n, a, b, Heap[], cnt = ;
inline void add(int x)
{
Heap[++cnt] = x;
int now = cnt;
while (now!=)
{
if (Heap[now] < Heap[now >> ])
swap(Heap[now], Heap[now >> ]),now>>=;
else
break;
}
}
inline void pop()
{
printf("%d\n", Heap[]);
Heap[] = Heap[cnt--];
int root = ;
while (root << <= cnt)
{
int son;
if ((root << ) + > cnt ||
Heap[root << ] < Heap[(root << ) + ])
{
son = root << ;
}
else
son = (root << ) + ;
if (Heap[son] > Heap[root])
break;
swap(Heap[root], Heap[son]);
root = son;
}
}
int main()
{
scanf("%d", &n);
for (int i = ; i <= n; ++i)
{
scanf("%d", &b);
add(b);
}
while(n)
{
pop();
n--;
}
return ;
}

值得注意的是,如果把一整个堆按照下标顺序输出去,往往是无序的

原因是这个:

堆是一个完全二叉树,所以所谓大小关系仅仅是一个树根和他的两个智障儿子的关系,而不是说按顺序输出一定是有序数列,

堆排序能完成排序,其实是依靠每一次都弹出堆顶元素,然后进行动态维护,所以最终输出的数列是一个有序数列。

上面是堆排,下面是快排,由此可见堆排的确是很快的

最后一个(超级无敌变态的做法)

c++自带STL

其实就是sort函数

头文件是#include <algorithm>

Sort函数有三个参数:

(1)第一个是要排序的数组的起始地址。
(2)第二个是结束的地址(最后一位要排序的地址的下一地址)
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。

其实还是挺简单的吧。。。。。。。

主要是排序能够练习对于数组的运用,这是培养思维和能力的好方法,至于考场上嘛,,,,,,还是sort好啊(雾

最后,我们贴一下AC代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
int findPos(int a[], int low, int high)
{
//将小于t的元素赶到t的左边,大于t的元素赶到t的右边
int t = a[low];
while (low < high)
{
while (low < high && a[high] >= t)
high--;
a[low] = a[high];
while (low < high && a[low] <= t)
low++;
a[high] = a[low];
}
a[low] = t; //返回此时t在数组中的位置
return low;
} //在数组中找一个元素,对于大于该元素和小于该元素的两个数组进行再排序,
//再对两个数组分为4个数组,再排序,直到最后每组只剩下一个元素为止
void quickSort(int a[], int low, int high) //快速排序
{
if (low > high)
return;
int pos = findPos(a, low, high);
quickSort(a, low, pos - );
quickSort(a, pos + , high);
}
int main()
{
int n, a[];
scanf("%d", &n);
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]);
quickSort(a, , n);
for (int i = ; i <= n; i++)
cout << a[i] << " ";
cout << endl;
return ;
}

P1177 【模板】快速排序(学完归并和堆排之后的二更)的更多相关文章

  1. Golang入门(2):一天学完GO的基本语法

    摘要 在配置好环境之后,要研究的就是这个语言的语法了.在这篇文章中,作者希望可以简单的介绍一下Golang的各种语法,并与C和Java作一些简单的对比以加深记忆.因为这篇文章只是入门Golang的第二 ...

  2. 在w3cschool学完html,css,javascript,jquery以后,还是不会做前端怎么办?

    w3cschool是一个非盈利性的在线技术学习网站,提供按W3C标准编写的基础教程.完整的看完w3cschool上面的手册,可以基本掌握编程语法.基础性的东西通常都会比较零散,因此,在学习一段时间后, ...

  3. 7天学完Java基础之0/7

    笔记-7天学完Java基础之0/7 1.常用命令提示符(cmd) 启动:Win+R,输入cmd​

  4. python 快排,堆排,归并

    #归并排序 def mergeSort(a,L,R) :     if(L>=R) :         return     mid=((L+R)>>1)     mergeSort ...

  5. 学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat

    学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat 2019-05-09   19:28:42 注:项目(MyEclipse)创建的时候选择:Web Service Pr ...

  6. 零基础学完Python的7大就业方向,哪个赚钱多?

    “ 我想学 Python,但是学完 Python 后都能干啥 ?” “ 现在学 Python,哪个方向最简单?哪个方向最吃香 ?” “ …… ” 相信不少 Python 的初学者,都会遇到上面的这些问 ...

  7. Golang入门(3):一天学完GO的进阶语法

    摘要 在上一篇文章中,我们聊了聊Golang中的一些基础的语法,如变量的定义.条件语句.循环语句等等.他们和其他语言很相似,我们只需要看一看它们之间的区别,就差不多可以掌握了,所以作者称它们为&quo ...

  8. 0基础如何更快速入门Linux系统?学完Linux有哪些就业方向?

    Linux系统是使用Linux内核及开源自由软件组成的一套操作系统,是一种类UNIX系统,其内核在1991年10月5日由林纳斯·托瓦兹首次发布. 它的主要特性:Linux文件一切皆文件.完全开源免费. ...

  9. 3分钟学完Python,直接从入门到精通

    作为帅气小编,我已经把python一些模块的甩在这儿了qwq,只要你拿到这些干货,包你玩转python,直接冲向"大佬"的段位,如果已经学了C或者C++或者说如果你需要你的一段关键 ...

随机推荐

  1. 基础知识:if判断、while循环、for循环

    今日学习内容                   1.if 判断(流程控制的一种) 写重复的代码是程序员最不耻的行为,所以我们需要while循环和for循环 ,^_^!                 ...

  2. Java并发编程实战 之 对象的共享

    上一篇介绍了如何通过同步多个线程避免同一时刻访问相同数据,本篇介绍如何共享和发布对象,使它们被安全地由多个进程访问. 1.可见性 通常,我们无法保证执行读操作的线程能看到其他线程写入的值,因为每个线程 ...

  3. webstorm 2018.2.3 cmd+w无法关闭文件

  4. 洛谷P3366 【模板】最小生成树(Boruvka算法)

    题意 题目链接 Sol 自己yy着写了一下Boruvka算法. 算法思想很简单,就是每次贪心的用两个联通块之间最小的边去合并. 复杂度\(O(n \log n)\),然鹅没有Kruskal跑的快,但是 ...

  5. hbase 预分区与自动分区

    我们知道,HBASE在创建表的时候,会自动为表分配一个Region,当一个Region过大达到默认的阈值时(默认10GB大小),HBase中该Region将会进行split,分裂为2个Region,以 ...

  6. centos7新增硬盘

    centos7新增硬盘 步骤:分区---格式化---挂载(配置开机自动挂载) 1.分区 fdisk -l 查看硬盘信息确认新硬盘的名称(以/dev/sdb为例) fdisk /dev/sdb  管理硬 ...

  7. tmux resurrect 配置

    概述 tmux 用了很长时间了, 快捷键定制了不少, 唯一的遗憾是没法保存 session, 每次关机重开之后, 恢复不到之前的 tmux session. 虽然也能忍受, 但是每天都手动打开之前的 ...

  8. LINQ 之 GroupBy

    声明:本文为www.cnc6.cn原创,转载时请注明出处,谢谢! 本文作者文采欠佳,文字表达等方面不是很好,但实际的代码例子是非常实用的,请作参考. 一.先准备要使用的类: 1.Person类: cl ...

  9. openstack 2019/4/28

    官网参考地址:https://docs.openstack.org/keystone/queens/install/index-rdo.html (但愿能看懂) 环境:这个部分解释如何按示例架构配置控 ...

  10. HashMap、Hashtable、ConcurrentHashMap的原理与区别

    同步首发:http://www.yuanrengu.com/index.php/2017-01-17.html 如果你去面试,面试官不问你这个问题,你来找我^_^ 下面直接来干货,先说这三个Map的区 ...