顺序统计量

一、顺序统计量

        定义:将长度为 n 的数组按升序排序后,第 i 个位置的数字是该数组的第 i 小的量,称之为第 i 顺序统计量。

则一个数组中的最小值是第1顺序统计量,最大值是第n顺序统计量,中位数是第 (n+1)/2 顺序统计量 (向下取整)

二、求最大值和最小值

        最简单的方法就是将数组扫描一遍,找出其中的最大值与最小值,求出第1顺序统计量和第n顺序统计量。 时间复杂度即为 O(n)

#include<stdio.h>
#include<string.h>
int maxn,minn=100001,n,a[10001];
int max(int a,int b)
{
	if(a<b) return b;
	else return a;
}
int min(int a,int b)
{
	if(a<b) return a;
	else return b;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		maxn=max(maxn,a[i]);
		minn=min(minn,a[i]);
	}
	printf("%d %d",maxn,minn);
	return 0;
} 

三、求第k顺序统计量

        借助排序算法,直接通过已排序的数组 a [k] 即可完成,时间为排序算法的时间,快速排序,归并排序O(nlogn) ,冒泡排序,插入排序O(n^{2}),但是这些方法无疑浪费时间,排序进行了许多不必要的操作。

        数组的划分

        快速排序是通过数组的划分实现的,数组划分有多种方法。

        1.第一种划分方法

// 以 a[left]为基准,将操作后的数组变为 a[left]所在位置的左边全部都小于 a[left]
// a[left]所在位置的右边全部都大于 a[left]
//即若k为a[left]的下标 a[left]为第k顺序统计量                               

if(left>=right) return;
	int temp=a[left];
	int i=left,j=right;
	while(i!=j)
	{
		while(a[j]>=temp && i<j) j--;
		while(a[i]<=temp && i<j) i++;
		int t=a[i]; a[i]=a[j]; a[j]=t;
	}
	int t=a[left]; a[left]=a[i]; a[i]=t;

算法实现过程: 这里可以了解到具体操作 (深入理解快速排序) 

         2.第二种划分方法

// 第二种划分方法,此时快速排序伪代码

int partition(int a[],int left,int right)
{
	int x=a[right];
	int i=left-1;
	for(int j=left;j<=right-1;j++)
	if(a[j]<=x)
	{
		i++;
		swap(a[i],a[j]);
	}
	swap(a[i+1],a[right]);
	return i+1;
}
void quick_sort(int a[],int l,int r)
{
	if(l<r)
	{
		int q=partition(a,l,r);
		quick_sort(a,l,q-1);
		quick_sort(a,q+1,r);
	}
 } 

 算法实现过程:以 a[]=[2,8,7,1,3,5,6,4]为例

      法一   数组划分求出第k顺序统计量

        1.先将数组中的某个元素(通常为数组末尾元素)按照上述方法划分左右两个区域(左边元素小于该元素,且右边元素大于该元素),并求出该元素的下标 a[ q ],此时该元素为 第 q 顺序统计量。

        2.需要知道第k顺序统计量,则需要k与q进行比较,若 k<q 则只需要在左区域中找出第k小的数即可,同理若 k>q ,需要在右区域中找出第 k-q 小的数。

        3.依次不断递归,直至划分出第k顺序统计量为止。

注意:每次数组划分元素后返回的q是数组下标,若某区域 [ l , r ] 中的元素通过划分返回的q,对应在区域中的顺序统计量为 q-l+1

int randselect(int a[],int l,int r,int k)
{
	int q=partition(a,l,r);
	int x=q-l+1;  // 在[l,r]的第x位  [1,n]的第q位 
	if(x==k) return a[q];
	if(k<x) return randselect(a,l,q-1,k);
	else return randselect(a,q+1,r,k-x); 
}

法二  select算法----最坏情况为线性时间的选择算法

算法实现思路:

 难点: select 函数 寻找中位数的中位数函数 find

关于select函数:

        先找出中位数的中位数,再通过数组划分将数组以该数为基准划分。

关于find函数:

        先将所有的数分为若干个小组,再在每个小组通过插入排序的方法,取出所有小组的中位数构成一个中位数数组(对于多出来的若干个元素同样取其中位数),再通过select选择算法,找出中位数数组的中位数(涉及两个函数的互相递归,较繁琐)

取中位数代码(注意区域左端L):

for(int i=1;i<num;i++)  // 找出每组的中位数,并将其归为一个数组 
	mid[i]=ar[5*i-3+l];
if(h%5==0) mid[num]=ar[5*num-3+l];
else   mid[num]=ar[5*(num-1)+l+(h%5-1)/2];

如图:找出中位数数组的中位数43,再进行partition将整个数组划分,再重复递归下去,直至找到需要找的那个第k顺序统计量 。

#include<stdio.h>
#include<iostream>
using namespace std; 
#include<string.h>
int a[10001],n,num,k;
int mid[10001];
int find(int ar[],int l,int r);
void insertsort(int l,int r) // 插入排序 
{
	for(int i=l;i<=r;i++)
	{
		int x=a[i];
		int j=i-1;
		while(j>=l && a[j]>x)
		{
			a[j+1]=a[j];
			j--;
		}
		a[j+1]=x;
	}
}
int partition(int ar[],int l,int r,int t)  // 数组划分 
{
	int i=l-1;
	int k;
	for(int j=l;j<=r;j++)
		if(ar[j]==t) k=j;
	swap(ar[k],ar[r]);
	for(int j=l;j<r;j++)
	{
		if(ar[j]<=t)
		{
			i++;
			swap(ar[j],ar[i]);
		}
	}
	swap(ar[i+1],ar[r]);
	return i+1;
}
int select(int ar[],int l,int r,int q)
{
	if(l>=r){
		return ar[l];
	}
	int t=find(ar,l,r);  //返回的 t 代表的是 存储每一组中位数的临时数组的中位数
	int mi=partition(ar,l,r,t);
	int k=mi-l+1;  //得到低区的元素个数
	if(q==k){  //表明已经找到该元素 
		return ar[mi];
	} 
	else if(q<k){  //则要递归在 低区查找 
		return select(ar,l,mi-1,q);
	}
	else{  //递归在高区查找 
		return select(ar,mi+1,r,q-k);  //在整个数组中的第i小元素在高区应该是 第 i-k 小元素了 
	}
}
int find(int ar[],int l,int r)
{
	int h=r-l+1;
	if(h%5==0) num=h/5;
	else num=h/5+1;
	int p1=l,p2=min(p1+4,r);
	for(int i=1;i<=num;i++)  // 将每含5个元素的组进行插入排序 
	{
		insertsort(p1,p2);
		p1=min(p2+1,r);
		p2=min(p1+4,r);
	}
	for(int i=1;i<num;i++)  // 找出每组的中位数,并将其归为一个数组 
		mid[i]=ar[5*i-3+l];
	if(h%5==0) mid[num]=ar[5*num-3+l];
	else   mid[num]=ar[5*(num-1)+l+(h%5-1)/2];
	if(num==1) return mid[1];
	else return select(mid,1,num,(1+num)/2);  //找出中位数的中位数 
}
int main()
{
	scanf("%d",&n);scanf("%d",&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	printf("%d",select(a,1,n,k+1));
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/525388.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图像识别网络与训练策略——基于经典网络架构训练图像分类模型

基于经典网络架构训练图像分类模型 总体框架 数据预处理部分&#xff1a;- 数据增强&#xff1a;torchvision中transforms模块自带功能&#xff0c;比较实用 - 数据预处理&#xff1a;torchvision中transforms也帮我们实现好了&#xff0c;直接调用即可 - DataLoader模块直接…

@四年级家长,这条香港优才计划+华侨生联考捷径,一定要看!

四年级家长&#xff0c;这条香港优才计划华侨生联考捷径&#xff0c;一定要看&#xff01; 香港身份的优势有多大&#xff1f;进可参加华侨生联考400分上内地985/211大学&#xff0c;退可参加香港DSE轻松上香港本地大学和海外高校。 但香港身份对子女的教育优势大小&#xff0c…

C++从入门到精通——this指针

this指针 前言一、this指针的引出问题 二、this指针的特性三、例题什么时候会出现编译报错什么时候会出现运行崩溃this指针存在哪里this指针可以为空吗 四、C语言和C实现Stack的对比C语言实现C实现 前言 this指针是一个特殊的指针&#xff0c;在C类的成员函数中使用。它指向调…

PPT 操作

版式 PPT中&#xff0c;巧妙使用母版&#xff0c;可以提高效率。 双击母版&#xff0c;选择其中一个版式&#xff0c;插入装饰符号。 然后选择关闭。 这个时候&#xff0c;在该版式下的所有页面&#xff0c;就会出现新加入的符号。不在该版式下的页面&#xff0c;不会出现新加…

【Redis】Redis的使用

登录redis [roottest2 ~]# redis-cli 127.0.0.1:6379> 或[roottest2 ~]# redis-cli -h 192.168.67.12 -p 6379 192.168.67.12:6379> redis-benchmark 测试工具 redis-benchmark 是官方自带的Redis性能测试工具&#xff0c;可以有效的测试Redis服务的性能 基本的测试语…

2.类与对象(上篇)

1.面向过程和面向对象初步认识 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完成。 2.类的引入 C**语言结构体中只能定义变量&#xff0c;在C中&#xff0c;结构体内不仅可以定义变量&#xff0c;也可以定…

(三)LTspice学习交流分析

文章目录 前言一、Edit simulation cmd二、添加激励总结 前言 上一节我们学习了LTspice的安装&#xff0c;很简单&#xff0c;无脑安装 &#xff08;一&#xff09;LTspice简介 &#xff08;二&#xff09;LTspice学习之简介2 今天我们来学习一下LTspice另一个非常重要的仿真功…

血泪教训!程序员副业接单做私活避坑指南!!!

缘起 经常有粉丝朋友向我哭诉留言&#xff0c;告知大白自己兼职被骗的经历&#xff1a; 在大家找兼职踩坑过程中&#xff0c;我总结下来就是以下几点血泪教训&#xff1a; 1. 有没有靠谱兼职推荐&#xff1f; 2. 零基础怎么兼职接单&#xff1f; 3. 怎么渗透&#xff1f;怎么…

C++设计模式:桥模式(五)

1、定义与动机 桥模式定义&#xff1a;将抽象部分&#xff08;业务功能&#xff09;与实现部分&#xff08;平台实现&#xff09;分离&#xff0c;使他们可以独立地变化引入动机&#xff1a; 由于某些类型的固有的实现逻辑&#xff0c;使得它们具有两个变化的维度&#xff0c;…

2.k8s架构

目录 k8s集群架构 控制平面 kube-apiserver kube-scheduler etcd kube-controller-manager node 组件 kubelet kube-proxy 容器运行时&#xff08;Container Runtime&#xff09; cloud-controller-manager 相关概念 k8s集群架构 一个Kubernetes集群至少包含一个控制…

飞书API(3):Python 自动读取多维表所有分页数据的三种方法

上一小节介绍了怎么使用 Python 读取多维表的数据&#xff0c;看似可以成功获取到了所有的数据&#xff0c;但是在实际生产使用过程中&#xff0c;我们会发现&#xff0c;上一小节的代码并不能获取到所有的多维表数据&#xff0c;它只能获取一页&#xff0c;默认是第一页。因为…

MySQL的存储引擎、索引与事务

常见的端口号 MySQL–3306http–80https–443tcp–23fcp–21tomcat–8080ssh–22oracle–1521rockermq–9876 存储引擎 使用指令查看所有引擎&#xff1a; show engines;从图中可以看出MySQL默认的存储引擎是InnoDB&#xff1b;并且在5.7版本所有的存储引擎中只有 InnoDB 是…

亮数据----教你轻松获取数据

文章目录 1. 数据采集遇到的瓶颈1.1 不会造数据&#xff1f;1.2 不会写爬虫代码&#xff1f; 2.IP 代理基础知识2.1 基本概念2.2 作用和分类2.3 IP 代理的配置和使用2.4 安全和合规 3. 为何使用亮数据 IP 代理3.1 拥有丰富的代理网络服务3.2 简单易操作的采集工具3.3 拥有各平台…

路由器对数据包的处理过程分析笔记

虽然TCP-IP协议中传输数据会在各个路由器再次经过物理层、链路层、网络层的解封装、加工、封装、转发&#xff0c;但是对于两个主机间的运输层&#xff0c;在逻辑上&#xff0c;应用进程是直接通信的。 路由器主要工作在网络层&#xff0c;但它也涉及到物理层和链路层的一些功能…

PWM 脉宽跟随方案介绍

1. 前言 数字电源产品在使用桥式电路拓扑或是多路交错控制中&#xff0c;有时会需要滞后臂的 PWM 脉宽严格跟随超前臂的 PWM 脉宽&#xff0c;或从路的 PWM 脉宽严格跟随主路的 PWM 脉宽&#xff0c;本文将介绍如何利用高精度定时器实现 PWM 输出脉宽跟随&#xff0c;一种使用…

ai智能电销机器人的核心技术,工作原理和作用

科技快速发展的同时&#xff0c;带来了人工智能产品的普及。而ai智能电销机器人则成为推进电销行业的产物&#xff0c;那么ai智能电销机器人是如何帮助企业高效触客&#xff0c;有效地工作&#xff0c;效果又如何呢&#xff1f;我们一起来看看吧&#xff01; 一、ai智能电销机器…

软件的生命周期_瀑布模型

瀑布模型 描述软件生成到消亡的过程模型图 该模型目前实际工作中已不常用&#xff0c;但是该模型是其他新型模型的“鼻祖 瀑布模型的优点 每个阶段比较清楚&#xff0c;并且有对应的文档产生 当前一个阶段完成后&#xff0c;才开始后面的阶段&#xff08;一次性的&#xff09…

「媒体邀约」天津媒体邀约资源有哪些?媒体宣传现场报道

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 天津作为中国北方的重要城市&#xff0c;拥有丰富的媒体资源&#xff0c;可以为各类活动提供全面的媒体宣传和现场报道。以下是天津地区的媒体邀约资源&#xff1a; 1. 报纸媒体 - 《天…

如何搭建APP分发平台分发平台搭建教程

搭建一个APP分发平台可以帮助开发者更好地分发和管理他们的应用程序。下面是一个简要的教程&#xff0c;介绍如何搭建一个APP分发平台。 1.确定需求和功能&#xff1a;首先&#xff0c;确定你的APP分发平台的需求和功能。考虑以下几个方面&#xff1a; 用户注册和登录&#xff…

Redis从入门到精通(九)Redis实战(六)基于Redis队列实现异步秒杀下单

文章目录 前言4.5 分布式锁-Redisson4.5.4 Redission锁重试4.5.5 WatchDog机制4.5.5 MutiLock原理 4.6 秒杀优化4.6.1 优化方案4.6.2 完成秒杀优化 4.7 Redis消息队列4.7.1 基于List实现消息队列4.7.2 基于PubSub的消息队列4.7.3 基于Stream的消息队列4.7.4 基于Stream的消息队…