(p124)k分位数

  首先,这个题意思应该是:对一个包含n个元素的集合来说,k分位数是指能把有序集合分成k个等大小集合的k-1个顺序统计量,给出一个能找出某一集合的k分位数的O(nlgk)算法——书上多印了一个“第”字,搞得莫名其妙-_-;

  好吧,既然清楚了,我们来分析以下复杂度,lgk——这说明很有可能要用到分治,再根据递归树模型,我们就可以看出来,大概有这样一个函数:find(int *num,int k,int l,int r,int *result),它的功能是找到第(l+r)/2+1个分隔点对应的顺序统计量,存到result数组里面,然后递归地对左边和右边的区间进行操作。怎么找那个顺序统计量?这一章提到的两种算法都可以,而且这两种算法都顺带将数组分为了小于分割数的一部分和大于分割数的一部分,这保证了这道题分治算法的正确性。

/*
 * source.c
 *
 *  Created on: Feb 16, 2016
 *      Author: wing
 */
#include<stdio.h>
#include<stdlib.h>
int Select(int *num,int m,int l,int r)
{
	int i,j=l-1,tmp;
	if (l==r)
		return num[l];
	for (i=l;i<=r-1;i++)
		if (num[i]<num[r])
		{
			j++;
			tmp=num[j];
			num[j]=num[i];
			num[i]=tmp;
		}
	j++;
	tmp=num[j];
	num[j]=num[r];
	num[r]=tmp;
	if (m-1==j)
		return num[j];
	else
		if (m-1<j)
			return Select(num,m,l,j-1);
		else
			return Select(num,m,j+1,r);
}
int find(int *num,int k,int l,int r,int *result)/*注意哦,这里的k是每个小区间有k个元素^-^*/
{
	result[(l+r)/2]=Select(num,((l+r)/2+1)*k,l*k,(r+2)*k-1);
	if (l==r)
		return 0;
	else
	{
		find(num,k,l,(l+r)/2,result);
		find(num,k,(l+r)/2+1,r,result);
		return 0;
	}
}
int main(void)
{
	int *num,n,k,i,*result;
	scanf("%d",&n);
	scanf("%d",&k);
	num=(int *)malloc(sizeof(int)*n);
	for (i=0;i<n;i++)
		scanf("%d",&num[i]);
	result=(int *)malloc(sizeof(int)*k);
	find(num,n/k,0,k-2,result);
	for (i=0;i<=n/k-2;i++)
		printf("%d ",result[i]);
	return 0;
}


以下是使用R语言实现的SIM分位数变量选择技术的示例代码: ```R # 导入数据 data <- read.csv("data.csv") # 定义自变量和因变量 X <- data[, c("X1", "X2", "X3", "X4")] Y <- data$Y # 定义SIM分位数函数 sim_quantile <- function(z, tau) { if (tau < 0.5) { return(2 * tau * z) } else { return(2 * (1 - tau) * z) } } # 定义SIM分位数变量选择函数 sim_variable_selection <- function(X, Y, tau, alpha) { n <- nrow(X) p <- ncol(X) q <- round(sim_quantile(n, tau)) beta_hat <- rep(0, p) beta_tilde <- rep(0, p) residual <- Y active_set <- rep(FALSE, p) for (k in 1:q) { # 计算每个自变量的SIM分位数系数 sim_coef <- rep(0, p) for (j in 1:p) { if (!active_set[j]) { Xj <- X[, j] sim_coef[j] <- abs(cor(Xj, residual)) } } sim_coef_rank <- rank(sim_coef) j_k <- which.max(sim_coef_rank == (p - k + 1)) # 通过正交化法计算beta_tilde Xj_k <- X[, j_k] Xj_k_ortho <- Xj_k - X %*% solve(t(X) %*% X) %*% t(X) %*% Xj_k beta_tilde[j_k] <- sim_quantile(cor(Xj_k_ortho, residual), tau) # 判断是否加入变量 if (abs(beta_tilde[j_k]) > alpha) { active_set[j_k] <- TRUE X_active <- X[, active_set] beta_hat[active_set] <- solve(t(X_active) %*% X_active) %*% t(X_active) %*% Y residual <- Y - X_active %*% beta_hat[active_set] } else { beta_tilde[j_k] <- 0 } } return(beta_hat) } # 使用SIM分位数变量选择函数进行变量选择 beta_hat <- sim_variable_selection(X, Y, 0.5, 0.1) # 输出选择的变量系数 print(beta_hat) ``` 说明: - `sim_quantile`函数用于计算SIM分位数系数。 - `sim_variable_selection`函数用于实现SIM分位数变量选择技术。其中,`tau`为分位数的值,`alpha`为控制变量选择的严格程度的参数。 - 在代码中使用了正交化法来计算`beta_tilde`,以便减少多重共线性的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值