从一位数组中提取最小k个元素

本文介绍两种从整型数组中提取前K个最小整数的方法:一种使用快速排序的递归划分,另一种利用小根堆实现。通过具体代码示例展示了这两种算法的设计与实现。
#include <iostream>
#include <cstdlib>
#include <vector>

using namespace std;
/*
 * 从n个整型数组中提取前k个最小整数
 * 方法一:利用快速排序进行递归划分
*/
const int Max = 100;   // 数组最大容量
class Solution {
private:
	vector<int>array;  // 输入的数组 
	vector<int>kmin;   // 提取的k个最小值的数组
    /*   
	 * 对数组进行划分,返回“中值”位置
	*/
	int Adjust(vector<int>&arr, int low, int high) {
		int i, j;
		i = low;
		j = high;
		int tmp = arr[low];
		while(i < j) {
			while(i < j && arr[j] > tmp) j--;
			if(i < j) arr[i++] = arr[j];

			while(i < j && arr[i] < tmp) i++;
			if(i < j) arr[j--] = arr[i];

		}
		arr[i] = tmp;
		return i;
	}
    /*
	 * 利用上面的调整函数进行查找
	*/
	void JustDoIt(vector<int>&arr, int low, int high, int k) {
		int i;
		int mid = Adjust(arr, low, high);
		static bool find;     // 用于递归截断
		/*
		 * 找到解
		*/
		if(!find && (mid + 1 == k || mid == k)) {
			find = true;
			for(i = 0;i < k;i++) {
				kmin.push_back(arr[i]);
			}
			return;
		}
		/*
		 * 递归处理 
		*/
		else if(!find && k > mid + 1) {
			JustDoIt(arr, mid + 1, high, k);
		}
		else if(!find) {
			JustDoIt(arr, low, mid - 1, k);
		}
	}

public:
	Solution(int n) {
		if(n < 0 || n>= Max) {
			cerr<<"参数不合法!"<<endl;
			exit(1);
		}
		int i;
		int e;
		for(i = 0;i < n;i++) {
			cout<<"请输入第"<<i<<"个整数:";
			cin>>e;
			if(!cin.good()) exit(1);
			array.push_back(e);
		}
	}
	void JustDoIt(int k) {
		if(k <= 0 || k > array.size()) {
			cerr<<"参数不合法!"<<endl;
			exit(1);
		}
		JustDoIt(array, 0, array.size() - 1, k);
	}
	void show()  {
		vector<int>::iterator it;
		for(it = kmin.begin(); it != kmin.end(); it++) {
			cout<<*it<<endl;
		}
	}
};

void main() {
	Solution s(10);
	s.JustDoIt(3);
	s.show();
}




#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
/*
 * 从n个整型数组中提取前k个最小整数
 * 方法二:利用小根堆
*/
const int Max = 100;   // 数组最大容量
class Solution {
private:
	vector<int>array;  // 输入的数组 
	vector<int>kmin;   // 提取的k个最小值的数组
    /*   
	 * 堆调整
	*/
	void AjustHeap(vector<int>&arr, int i, int n) {
		int j;
		int tmp;
		tmp = arr[i];
		while(i < n) {
			j = 2 * i + 1;
			if(j >= n) break;
			if(j < n - 1 && arr[j] > arr[j + 1]) {
				j++;
			}
			if(tmp < arr[j]) break;
			arr[i] = arr[j];
			i = j;
		}
		arr[i] = tmp;
	}

public:
	Solution(int n) {
		if(n < 0 || n>= Max) {
			cerr<<"参数不合法!"<<endl;
			exit(1);
		}
		int i;
		int e;
		for(i = 0;i < n;i++) {
			cout<<"请输入第"<<i<<"个整数:";
			cin>>e;
			if(!cin.good()) exit(1);
			array.push_back(e);
		}
	}
	/*
	 * 建堆
	*/
	void CreateHeap(int n) {
		int i;
		for(i = n/2 - 1;i >= 0;i--) {
			AjustHeap(array, i, n);
		}
//		copy(array.begin(), array.end(), ostream_iterator<int>(cout," "));
//		cout<<"---"<<endl;
	}
	void JustDoIt(int k) {
		if(k <= 0 || k > array.size()) {
			cerr<<"参数不合法!"<<endl;
			exit(1);
		}
		int i;
		int n;
		for(i = 0;i < k;i++) {
			n = array.size() - i;
			CreateHeap(n);
//			copy(array.begin(), array.end(), ostream_iterator<int>(cout," "));
			swap(array[0],array[n-1]);
		}
        vector<int>::iterator it = array.end() - 1; 
		for(i = 0;i < k;i++) {
			kmin.push_back(*it--);
		}
	}
	void show()  {
		vector<int>::iterator it;
		for(it = kmin.begin(); it != kmin.end(); it++) {
			cout<<*it<<endl;
		}
	}
};

void main() {
	Solution s(3);
	s.JustDoIt(3);
	s.show();
}


<think>我们有两个主要任务: 1. 从一个数组提取4个连续的字节。 2. 将这4个字节按照大端序(高位在前)转换为浮点数。 根据用户上一次的问题,我们之前已经介绍了使用structnumpy的方法。但这次用户提到“从数组提取”,所以我们需要考虑数组的类型。数组可能是bytes、bytearray、列表(元素为整数)或numpy数组等。 这里我将提供几种常见情况的解决方案: 情况1:数组是bytes或bytearray对象 情况2:数组是列表(元素为0-255的整数) 情况3:数组是numpy数组元素为整数) 无论哪种情况,我们都需要先提取4个连续的字节,然后按照大端序转换为浮点数。 方法核心:使用struct.unpack('>f', bytes_slice) 或 numpy.frombuffer 步骤: 1. 从数组提取一个长度为4的切片(slice)。 2. 确保这个切片是4个字节(每个字节0-255)。 3. 使用转换函数。 注意:如果数组长度不足4,需要处理异常。 下面我们分别针对不同情况编写代码示例。</think># Python 从数组提取4字节并按大端序转为浮点数 在Python中从数组提取4个字节并按大端序(高位在前)转换为浮点数,可以使用多种方法。以下是详细的解决方案: ## 方法1: 使用struct模块(推荐) ```python import struct def extract_float_from_array(arr, start_index): """ 从数组提取4字节并按大端序转换为浮点数 参数: arr: 包含字节数据的数组(bytes、bytearray或整数列表) start_index: 提取起始位置索引 返回: 转换后的浮点数 """ if start_index + 4 > len(arr): raise IndexError("数组长度不足,无法提取4字节数据") # 提取4字节数据 byte_slice = arr[start_index:start_index+4] # 确保数据类型为bytes if isinstance(byte_slice, (list, bytearray)): byte_slice = bytes(byte_slice) # 大端序转换: '>'表示大端序,'f'表示32位浮点数 return struct.unpack('>f', byte_slice)[0] # 示例用法 byte_array = b'\x40\x49\x0f\xdb' # 字节数组 (对应浮点数3.14159) int_list = [0x40, 0x49, 0x0f, 0xdb] # 整数列表 bytearray_obj = bytearray(b'\x40\x49\x0f\xdb') # bytearray对象 # 从不同数组类型中提取并转换 print(extract_float_from_array(byte_array, 0)) # 输出: 3.1415927410125732 print(extract_float_from_array(int_list, 0)) # 输出: 3.1415927410125732 print(extract_float_from_array(bytearray_obj, 0)) # 输出: 3.1415927410125732 ``` ## 方法2: 使用numpy库(适合科学计算) ```python import numpy as np def numpy_extract_float(arr, start_index): """ 使用numpy从数组提取4字节并按大端序转换为浮点数 参数: arr: 包含字节数据的数组(bytes、bytearray或整数列表) start_index: 提取起始位置索引 返回: 转换后的浮点数 """ if start_index + 4 > len(arr): raise IndexError("数组长度不足,无法提取4字节数据") # 提取4字节数据并转换为bytes byte_data = bytes(arr[start_index:start_index+4]) # 创建大端序浮点数dtype dt = np.dtype('>f4') # 从字节缓冲区创建数组提取值 return np.frombuffer(byte_data, dtype=dt)[0] # 示例用法 float_value = numpy_extract_float([0x40, 0x49, 0x0f, 0xdb], 0) print(f"numpy转换结果: {float_value}") # 输出: 3.1415927410125732 ``` ## 方法3: 手动转换(理解原理) ```python def manual_extract_float(arr, start_index): """ 手动从数组提取4字节并按大端序转换为浮点数 参数: arr: 包含字节数据的数组(整数列表) start_index: 提取起始位置索引 返回: 转换后的浮点数 """ if start_index + 4 > len(arr): raise IndexError("数组长度不足,无法提取4字节数据") # 提取4个字节 b0, b1, b2, b3 = arr[start_index:start_index+4] # 合为32位整数(大端序) combined = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3 # 提取符号位(第31位) sign = -1 if (combined & 0x80000000) else 1 # 提取指数位(第23-30位) exponent = ((combined >> 23) & 0xFF) - 127 # 提取尾数位(第0-22位) fraction = combined & 0x7FFFFF # 计算浮点数值 return sign * (1 + fraction / 2**23) * (2 ** exponent) # 示例用法 float_value = manual_extract_float([0x40, 0x49, 0x0f, 0xdb], 0) print(f"手动转换结果: {float_value}") # 输出: 3.1415927410125732 ``` ## 关键概念说明 1. **大端序(高位在前)**: - 字节顺序:最高有效字节存储在最低内存地址 - 例如:浮点数3.14159的字节表示为`40 49 0f db` - 内存布局:`[0x40] [0x49] [0x0f] [0xdb]` 2. **IEEE 754单精度浮点数格式**: $$ \text{值} = (-1)^{\text{sign}} \times 2^{\text{exponent}-127} \times (1 + \text{fraction}/2^{23}) $$ - 1位符号位 - 8位指数位(偏移127) - 23位尾数位 3. **32位浮点数范围**: - 最大值:约$3.4 \times 10^{38}$ - 最小值:约$-3.4 \times 10^{38}$ - 最小正值:约$1.4 \times 10^{-45}$ ## 实际应用场景 1. **二进制文件解析**:读包含浮点数的二进制文件 2. **网络协议处理**:解析大端序网络协议中的浮点数据 3. **硬件接口**:处理传感器或设备返回的原始字节数据 4. **图像处理**:解析自定义图像格式中的浮点像素值[^1] ## 常见问题解答 **Q: 如果数组元素不是0-255范围内的整数怎么办?** A: 需要先进行规范化处理: ```python # 规范化数组元素到0-255范围 normalized_arr = [min(max(int(x), 0), 255) for x in arr] ``` **Q: 如何验证转换结果是否正确?** A: 可以使用在线IEEE 754转换器验证: ```python # 验证转换结果 test_value = 123.456 byte_rep = struct.pack('>f', test_value) converted = struct.unpack('>f', byte_rep)[0] print(f"原始值: {test_value}, 转换值: {converted}") ``` **Q: 如何处理数组中的小端序数据?** A: 只需将格式字符串从`'>f'`改为`'<f'`: ```python # 小端序转换 little_endian_value = struct.unpack('<f', byte_slice)[0] ``` ## 相关问题 1. 如何将浮点数按大端序转换为4字节数组?[^2] 2. Python中如何处理双精度(64位)浮点数的字节转换? 3. 如何优化大批量浮点数据的转换性能?[^3] 4. 32位浮点数与64位浮点数的精度差异有多大? 5. Python中如何处理浮点数的特殊值(NaN, Inf)? 6. 如何检测系统的字节序(大端序/小端序)?[^4] [^1]: 图像预处理中常涉及浮点数转换,如归一化像素值[^1] [^2]: 使用`struct.pack('>f', value)`可将浮点数转为大端序字节 [^3]: 对于大批量数据,使用numpy向量化操作可显著提升性能 [^4]: 使用`sys.byteorder`可检测系统字节序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值