排序和顺序统计学(1)

  也有好几天没记录算法学习情况了,这两天看了《算法导论》的第二部分,排序和顺序统计学,记录一下,也顺便增强记忆

1.堆排序

  就是最大堆和最小堆,用一维数组存储,数据结构是完全二叉树。主要过程分为构建最大/最小堆,插入操作,弹出最大值,取最大/最小值,改变堆中的权值。

  构建堆就是从第一个非叶子节点开始,倒数到第一个节点,对于每个节点执行以下函数(最大堆为例):

void heapify(int x)
{
int largest;
if (x*2<=heapsize&&a[x] > a[x * 2]) largest = x;
else largest = x * 2;
if (x*2+1<=heapsize&&a[x * 2 + 1]>a[largest]) largest = x*2+1;
if(x!=largest)
{
swap(a[largest],a[x]);
heapify(largest);
}
}

  对于每一个节点i,将它与它的两个子节点i*2和i*2+1进行比较,将最大元素放在三者中的父亲节点,并对之前存放最大元素的节点递归式用该函数,即可构建最大堆。时间复杂度为O(nlgn),对于每个元素,递归式用该函数的最大深度为lgn,每次递归时间复杂度为常数级,共对n/2个节点执行该函数,因此时间复杂度应为n/2*a*lgn,1/2及a都是常数,略去即得O(nlgn)

  取最值:将堆顶元素取出即可,时间复杂度为O(1)

  改变值操作:书中所说为increase函数,即对于最大堆来说,只有当值增大的时候才对其改变并进行操作,否则不进行操作。操作如下:将当前元素与他的父亲节点进行比较,若比父亲节点大则互换:

void increase(int pos,int x)
{
if(a[pos]<x)
{
a[pos] = x;
while(pos>1&&a[pos]>a[pos/2])
{
swap(a[pos],a[pos/2]);
pos = pos/2;
}
}
}//将x替换pos位置的元素

其实对于最大堆,当x<a[pos]时也是可以的,只要将调用increase函数改为调用heapify函数即可。(个人理解)

  添加值:数组长度++,并将数组末尾元素设为负无穷,对该元素调用函数increase(length[a],x),length[a]为数组a的长度,x为要插入数的大小。

  弹出最大值:即取最大值+删除堆顶元素。将堆顶元素与数组末尾元素互换,并对堆顶元素进行heapify操作即可

  输出堆排序结果:循环length[a]次弹出最值。

以上为堆排序的各种操作。

时间: 2024-10-10 16:43:02

排序和顺序统计学(1)的相关文章

读书笔记 -- 算法导论(第二部分 排序和顺序统计学)

输入数据的结构 在实际中,待排序的数很少是孤立的值,它们通常是一个称为记录的数据集的一部分.每个记录有一个关键字key,它是待排序的值.记录的其他数据称为卫星数据,即它们通常以key为中心传送.在一个排序的算法中,当交换关键字时,卫星数据也必须交换.如果记录都很大,我们可以交换一组指向各个记录的指针而不是记录本身,以求将数据移动量减少到最小. 在一定意义上,正式这些实现细节才使得一个完整的程序不同于算法.不管我们要排序的是单个的数值还是包含数据的大型记录,就排序的方法来说它们都是一样的.因为,为

排序和顺序统计学(2)——快速排序

快排我接触的也比较多了,从之前NOIP的时候算法老师讲的版本,到之前数据结构课上学习的版本,到现在<算法导论>里讲的版本,我个人并不能不能区别它们的好坏,权且都写出来,以后再来区别.三种实现方式如下: noip: void qsort1(int *a,int l,int r){ int i,j,mid,temp; i=l;j=r;mid=a[(i+j)/2]; while(i<=j) { while(a[i]<mid) i++; while(a[j]>mid) j--; if

算法导论 第9章 中位数和顺序统计学

/* * 算法导论 第九章 中位数和顺序统计学 * 线性时间选择元素 */ #include <iostream> #include <ctime> using namespace std; int minimum(int *arr, int len); int randomizedSelect(int *arr, int p, int r, int i); int randomizedPartition(int *arr, int p, int r); void exchange

C#字典Dictionary排序(顺序、倒序)

这里是针对.NET版本过低的排序方式,没怎么用过,记录一下: 一.创建字典Dictionary 对象 假如 Dictionary 中保存的是一个网站页面流量,key 是网页名称,值value对应的是网页被访问的次数,由于网页的访问次要不断的统计,所以不能用 int 作为 key,只能用网页名称,创建 Dictionary 对象及添加数据代码如下: Dictionary<string, int> dic = new Dictionary<string, int>(); dic.Add

算法导论-------------中位数和顺序统计学

文章来自网络加课本: 本次学习的内容讨论的问题是在一个由n个不同数值构成的集合中选择第i个顺序统计量问题.主要讲的内容是如何在线性时间内O(n)时间内在集合S中选择第i小的元素,最基本的是选择集合的最大值和最小值.一般情况下选择的元素是随机的,最大值和最小值是特殊情况,书中重点介绍了如何采用分治算法来实现选择第i小的元素,并借助中位数进行优化处理,保证最坏保证运行时间是线性的O(n). 1.基本概念 顺序统计量:在一个由n个元素组成的集合中,第i个顺序统计量是值该集合中第i小的元素.例如最小值是

算法导论第9章中位数和顺序统计学

#include <iostream> #include <stdint.h> #ifdef __linux #include <stdio.h> #endif // MINIMUM(A) // MIN = A[1] // for i = 2 to A.length // if min > A[i] // min = A[i] // return min int64_t minimum(int64_t* A, int64_t n) { int64_t min =

算法导论(第9章-中位数和顺序统计学)最大值和最小值

n个数中同时找出最大值跟最小值: 例子:n = 7 5  1  2  3  6  4  8 方法一:独立地找出最大值和最小值,各用n-1次比较,共有2n-2次比较. 方法二:成对地处理元素,先将一对输入元素相互比较,然后把较小者与当前最小值比较,把较大者与当前最大值比较,因此每两个元素需要比较3次.(n为奇数时,将最大值和最小值都设为第一个元素的值,然后成对地处理余下的元素,总共做了3*[n/2]次比较,[]为下界.n为偶数时,就对前两个元素做一次比较,以决定最大值和最小值的初始值,然后成对地处

算法导论

第一部分基础知识 插入排序(增量式方法) 归并排序(递归技术).分治法 第二部分排序和顺序统计学 堆排序.堆(优先级队列) 快速排序 计数排序.基数排序.桶排序 第三部分数据结构 栈.队列.链表 树 散列表 二叉查找树 红黑树 第四部分高级设计和分析技术 第五部分高级数据结构 第六部分图算法

C#文件和文件文件夹按时间、名称排序-顺序与倒序

对于文件和文件夹有多种排序方式,常用的就是按创建或修改时间.按文件名排序.在 C# 中,按时间和文件名排序都十分简单,用数组提供的排序方法 Array.Sort() 一行代码就可以搞定,当然也可以用常用的排序方法,如快速排序.冒泡排序等. 文件排序的方法也适用于文件夹,只是传递的变量不同.为了便于使用,将分别列出C#文件排序和文件夹排序四种常用方法,分别为:按名称顺序与倒序排序.按时间顺序与倒序. 一.C#文件排序 1.按名称顺序排列 /// <summary> /// C#按文件名排序(顺序