堆排序

选择排序

冷暖自知 提交于 2020-02-05 09:45:01
文章目录 内存的工作原理 数组和链表 读取 插入删除 选择排序 问题: 示例代码 内存的工作原理 计算机内存犹如一大堆抽屉,每个抽屉( 内存单元 )都有地址。 将数据存储到内存时,你请求计算机提供存储空间,计算机给你一个存储地址。需要存储多项数据时,有两种基本方式—— 数组 和 链表 。 数组和链表 数组的元素都在一起,即在内存中都是相连的。 在同一个数组中,所有元素的类型都必须相同(都为int、double等)。 链表的元素是分开的,其中每个元素都存储了下一个元素的地址。 读取 数组的 读取 速度很 快 ,因为你 知道其中每个元素的地址 ,支持 随机访问 ;链表只能 顺序访问 ,比如在需要读取链表的最后一个元素时,你不能直接读取,因为你 不知道它所处的地址 ,必须先访问元素#1,从中获取元素#2的地址,再访问元素#2并从中获取元素#3的地址,以此类推,直到访问最后一个元素。需要同时读取所有元素时,链表的效率很高:你读取第一个元素,根据其中的地址再读取第二个元素,以此类推。但如果你需要跳跃,链表的效率真的很低。 插入删除 链表的插入和删除速度很快。插入元素时,只需将其放入内存,并将其地址存储到前一个元素中。 在数组中添加新元素可能很麻烦。如果没有了空间,就得移到内存的其他地方,因此添加新元素的速度会很慢;如果需要在中间插入元素,则必须将后面的元素都向后移。 时间复杂度为 O ( n

openjudge:置换选择排序

回眸只為那壹抹淺笑 提交于 2020-02-05 05:11:13
1:置换选择排序 查看提交统计提问 总时间限制: 1000ms 内存限制: 65536kB 描述 给定初始整数顺串,以及大小固定并且初始元素已知的二叉最小堆(为完全二叉树或类似完全二叉树,且父元素键值总小于等于任何一个子结点的键值),要求利用堆实现置换选择排序,并输出第一个顺串。例如给定初始顺串29,14,35,13,以及堆(记为16 19 31 25 21 56 40), 置换选择排序得到的第一个顺串为16 19 21 25。 输入 第一行包含两个整数,m为初始顺串的数的个数,n为二叉最小堆的大小 第二行包含m个整数,即初始顺串 第三行包含n个整数,即已经建好的堆的元素(有序,按照从堆顶到堆底,从左到右的顺序) 输出 输出包含一行,即第一个顺串。 样例输入 4 7 29 14 35 13 16 19 31 25 21 56 40 样例输出 16 19 21 25 # include <iostream> # include <cstdio> using namespace std ; int myheap [ 100000 ] ; int tmp [ 100000 ] ; int m , n ; int last ; void shiftdown ( int k ) { int f = k ; int s = f * 2 + 1 ; int t = myheap [ f ] ;

排序算法

安稳与你 提交于 2020-02-05 03:05:24
10种排序算法总结(冒泡、选择、插入、希尔、归并、快速、堆、拓扑、锦标赛、基数) 2011年01月20日 星期四 08:24 P.M. 排序算法有很多,所以在特定情景中使用哪一种算法很重要。为了选择合适的算法,可以按照建议的顺序考虑以下标准: (1)执行时间 (2)存储空间 (3)编程工作 对于数据量较小的情形,(1)(2)差别不大,主要考虑(3);而对于数据量大的,(1)为首要。 主要排序法有: 一、冒泡(Bubble)排序——相邻交换 二、选择排序——每次最小/大排在相应的位置 三、插入排序——将下一个插入已排好的序列中 四、壳(Shell)排序——缩小增量 五、归并排序 六、快速排序 七、堆排序 八、拓扑排序 九、锦标赛排序 十、基数排序 一、冒泡(Bubble)排序 ----------------------------------Code 从小到大排序n个数------------------------------------ void BubbleSortArray() { for(int i=1;i<n;i++) { for(int j=0;i<n-i;j++) { if(a[j]>a[j+1])//比较交换相邻元素 { int temp; temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } } } } -----------------

【ARTS】01_05_左耳听风-20181210~1216

谁都会走 提交于 2020-02-05 02:31:39
ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algorithm 【leetcode】125验证回文串 https://leetcode.com/problems/valid-palindrome/ 1)problem 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。 说明:本题中,我们将空字符串定义为有效的回文串。 示例 1: 输入: "A man, a plan, a canal: Panama" 输出: true 示例 2: 输入: "race a car" 输出: false 2)answer 1、普通思路 把数字和字符提取出来,然后如果是字母就转换为小写。加到新的字符串中。 对于这个新的字符串,使用一个多条件循环,分别从字符串头、字符串尾遍历字符串的中间值,如果不一致就退出。直到遍历结束还是一致就判定为回文字符串。 2、高级思路 在discuss看到的答案。 用一个大循环分别从字符串头、字符串尾遍历字符串的中间值,里面两个小循环,用isalnum()函数判断是不是字母数字,如果不是就向前移动指针。 https://leetcode.com/problems/valid-palindrome

二叉堆/堆排序概念理解以及Java语言实现(学习笔记)

允我心安 提交于 2020-02-04 09:07:40
二叉堆/堆排序概念理解以及Java语言实现(学习笔记) 1.基础概念介绍 (1)满二叉树:每一层都达到了最大节点数,高度为h的满二叉树节点数为pow(2,h)-1 ( pow(x,y)代表x^y ) 如图所示: (2)完全二叉树:高度为h的二叉树每一个节点都和高度为h的满二叉树节点编号一一对应,那么它就是满二叉树。 如图所示: [1] 高度为h的完全二叉树节点数取值范围[pow(2,h-1),pow(2,h)-1],可见完全二叉树的高度是O( log(n) ) [2] 满二叉树是特殊的完全二叉树 [3]根节点编号记为1,对于节点i,它的左孩子编号为2i,右孩子编号为2i+1,对于节点i,它的父节点为floor(i/2) (floor表示向下取整)。完全二叉树适合用顺序存储结构来表示 (4)二叉堆概念: [1] 首先是一颗完全二叉树 [2] 小根堆:任何一个节点小于等于它的左孩子且小于等于他的右孩子 [3] 大根堆:任何一个节点大于等于它的左孩子且大于等于他的右孩子 举个例子(大根堆): 2.堆排序 [1] 堆排序属于选择排序,第i趟在n-i+1个元素中选择最大(值),作为子序列的第i个元素。 [2]和AVL树、红黑树、B树和B+树不同,他们是用于 查找 的,但堆是用于 排序 的。 2.1 建立大根堆 (在已有序列基础上建立) 设序列长度为n,则最后一个父节点编号为floor(n/2

堆排序

被刻印的时光 ゝ 提交于 2020-02-03 16:29:01
#include<iostream> using namespace std; const int maxn=100010; int n,m,heap[maxn],sz; void down(int u) { int t=u; if(2*u<=sz&&heap[2*u]<heap[t]) t=2*u;//一定要和 heap[t] 比较才能找到最小值 if(2*u+1<=sz&&heap[2*u+1]<heap[t]) t=2*u+1; if(t!=u) { swap(heap[u],heap[t]); down(t); } } void up(int u) { if(u/2&&heap[u/2]>heap[u]) { swap(heap[u/2],heap[u]); up[u/2]; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&heap[i]); sz=n; for(int i=(n+1)/2;i;i--)//堆的初始化 O(n) down(i); for(int i=1;i<=m;i++) { printf("%d ",heap[1]); heap[1]=heap[sz--];//弹出堆顶 down(1); } return 0; } 来源: CSDN 作者: 该用户已被删除QAQ

堆排序

不问归期 提交于 2020-02-03 13:45:18
堆排序 预备知识 满二叉树: 除最后一层结点均无任何子节点外,每一层的所有结点都有两个子结点的树。也就是每一层节点个数都是最大值的二叉树(每层 k k k 的节点个数= 2 k − 1 2^{k-1} 2 k − 1 ),也可以说除了叶子结点之外的每一个结点都有两个孩子,每一层(当然包含最后一层)都被完全填充。 完全二叉树: 如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。 所以一个满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。 堆: 堆是一个完全二叉树,可以分为大根堆(最大堆)和小根堆(最小堆) 大根堆:对于任意一个子树,父节点的值大于等于其左右孩子的值 小根堆:对于任意一个子树,父节点的值小于等于其左右孩子的值 一些性质: 假如用一个数组存储一个堆,那么节点 i i i 的左右孩子的下标分别为 2 i + 1 2i+1 2 i + 1 和 2 i + 2 2i+2 2 i + 2 ,其父节点的下标为 i − 1 2 \frac{i-1}{2} 2 i − 1 ​ 。如果设叶子节点的高度为1,那么一个长度为 n n n 的数字可以构建的完全二叉树的高度为 h = l o g n h = logn h = l o g n 。 数组构建堆 根据上面的预备知识,一个堆可以分为大根堆和小根堆,如何使用一个数组构建一个堆呢

堆排序

对着背影说爱祢 提交于 2020-02-02 03:57:52
了解堆排序前,需要先了解二叉树(请自行了解) 首先堆排序是 完全二叉树 ,大根或者小根,随便,然后父节点得到 左孩子2i+1,右孩子2i+2,孩子得到父亲(i-1)/2 堆排序——堆的 向下调整 性质 假设根节点的左右子树都是堆,但根节点不满足堆的性质,也就是不满足大根或者小根 可以通过一次向下的调整来将其变成一个堆。 以大根堆举例,先把 根 取下来,比如 2 ,就需要一个元素填上去,找左右孩子 最大 的移上去,比如 左孩子是9 , 右孩子8 ,把 9 移上去,那么 9 这个位置空着,如果2满足比9孩子都大,比如 0,1 ,直接2填上去,不满足,比如 6,4 ,继续重复之前操作,把 6 移上去,最后发现 4是叶子节点 ,那么把 2填到6 的位置,结束排序。 现在,我们经过排序得到了一个大根堆 ,我们需要挨个出数,从根开始, 9 移出来,把堆得最后一个元素比如 3 填上去,然后进行向下调整,调整结束后继续移出根,比如 8 ,重复直到全部移出,最后得到一个有序列表。 那么首先我们需要构造堆,把根想象成省长,孩子是市长,接着是县长,村长,如果我们要让省长管好省,那么我们需要先让市长管理好市,也就是要让最下级首先管理好自身,往上调整,直到市长。也就是先找到最后一个 非叶子节点 ,将它 向下调整 为大根堆,接着找前一个村,接着找县,接着前一个县(注意是 从右往左找 ,因为完全二叉树的特性)。

堆排序

橙三吉。 提交于 2020-02-02 03:53:13
堆排序 对于一个数组,我们可以用完全二叉树来表示.其第一个元素是它的根节点. 下标i的元素,其左孩子节点是2i+1,右孩子节点是2i+2,根节点是(i-1)/2 大根堆:任何一棵子树的root都是这棵子树的最大值 小根堆:任何一棵子树的root都是这棵子树的最小值 建堆(自下而上) 给定一个数组,如果想利用堆结构去进行逻辑运算,首先要建立一个堆(大根堆or小根堆)。建堆的时候应该自行脑补一下完全二叉树,尽管我们的遍历,交换都是在数组中完成的。 拿建立大根堆来说 遍历数组,遍历到的元素跟根节点比较,如果比根节点大,就交换。但是此时还需要跟已交换节点的根节点比较,总之就是 一直保证每棵子树root都是此子树的最大值! import java . util . Arrays ; /** * 对于一个数组,我们可以用完全二叉树来表示.其第一个元素是它的根节点. * 下标i的元素,其左孩子节点是2i+1,右孩子节点是2i+2,根节点是(i-1)/2 * 大根堆:此二叉树的树根是整棵树中的最大值 * 小根堆:~是最小值 */ public class HeapSort { public static void main ( String [ ] args ) { int [ ] arr = new int [ ] { 2 , 5 , 6 , 4 , 1 , 8 } ; System . out

堆排序-TOPK问题

廉价感情. 提交于 2020-02-01 16:14:14
现在有n个数,设计算法得到前k大的数。(k<n) 首先从原列表截取前K个元素,组成一个新列表。 然后将这个新列表构建成一个小根堆,那么根就新列表中最小的数。 接着继续从原列表取出K以后的元素,和小根堆根比对,如果比根小,那么肯定不属于前K大的数,如果比根大,替换根,然后做一次向下调整,根重新变成新列表最小的数,接着继续从原列表取数比对,直到取到原列表最后。 那么就可以得到一个前K大的数字组成的小根堆 ,最后出数 先上一下 成果 代码如下 public void TOPK(List<int> li,int k) { PrintList(li,":初始列表"); List<int> ki = new List<int>(k);//截取K个元素组成新数组 if (k<li.Count) { for (int i = 0; i < k; i++) { ki.Add(li[i]); } } PrintList(ki,":前"+k+"个元素组成的列表"); int n = ki.Count;//新列表长度 for (int i = ((n - 1 - 1) / 2); i > -1; i--)//从新列表最后一个元素的父节点开始向上调整 { Sift(ki, i, n - 1, false);//最上层就是i,最下层一直指向最后一个元素 }//得到一个小根堆 PrintList(ki,"