插入排序实现数据流中的中位数
题目描述
设计一个算法,用来计算数据流中的中位数。当数据流中读出奇数个数值时,中位数就是所有数值排序之后位于中间的数值;当数据流中读出偶数个数值时,中位数就是所有数值排序之后中间两个数的平均值。
功能要求
- Insert(num):从数据流中读取一个整数,并将其插入到有序数组中
- GetMedian():返回当前读取数据的中位数
数据范围
- 数组大小限制:1000
- 确保数据流中所有整数都在 int 范围内
解题思路
本题采用有序数组的方式实现,主要思路如下:
- 使用一个全局数组保存所有数据
- 每次插入时保持数组有序
- 根据数组长度的奇偶性计算中位数
算法流程
- 插入数据时,先将数据加入数组末尾
- 通过插入排序的方式维护数组有序性
- 获取中位数时,根据数组长度判断返回中间位置或中间两个数的平均值
代码实现
c
/**
* 全局变量声明区
*/
#include <math.h>
// 定义一个固定大小的数组来存储数据流中的数字
int arr[1000];
// 定义top指针,初始化为-1表示空数组
// top表示当前数组中最后一个元素的索引
int top = -1;
/**
* Insert函数:将新的数字插入到数组中,并保持数组有序
* @param num: 要插入的新数字
* @return: 无返回值
* 算法思路:使用插入排序的思想,每次插入后保持数组有序
*/
void Insert(int num) {
// 先将新数字插入到数组末尾
// ++top先自增再使用,所以先给top加1,再在新位置存入数字
arr[++top] = num;
// 使用插入排序的思想,将新插入的数字调整到正确的位置
// i>0确保不会数组越界
// arr[i]<arr[i-1]判断当前数字是否小于前一个数字
for(int i = top; i > 0 && arr[i] < arr[i-1]; i--) {
// 如果当前数字小于前一个数字,则交换它们的位置
int temp = arr[i]; // 暂存当前数字
arr[i] = arr[i-1]; // 将前一个数字后移
arr[i-1] = temp; // 将当前数字放到前一个位置
}
// 打印当前插入的结果
// top表示当前位置,arr[top]表示当前位置的数字
printf("arr%d=%d", top, arr[top]);
}
/**
* GetMedian函数:计算当前数组中所有数字的中位数
* @param: 无参数
* @return: 返回中位数,double类型
* 算法思路:根据数组长度的奇偶性来决定返回中间一个数还是中间两个数的平均值
*/
double GetMedian() {
// 通过判断top的奇偶性来确定数组长度的奇偶性
// top是索引,所以实际长度是top+1
if(top % 2 == 0) {
// 如果top是偶数,说明数组长度是奇数
// 直接返回中间位置的数字
// 需要转换为double类型以确保精确度
return (double)arr[top/2];
} else {
// 如果top是奇数,说明数组长度是偶数
// 返回中间两个数字的平均值
// 使用2.0来进行浮点数除法,确保结果的精确度
return (arr[top/2] + arr[top/2+1]) / 2.0;
}
}
代码详解
1. 全局变量
c
int arr[1000]; // 存储数据的数组
int top = -1; // 数组当前末尾索引
- arr:用于存储所有插入的数据
- top:记录当前数组最后一个元素的索引,初始为-1表示空数组
2. Insert 函数
c
void Insert(int num) {
arr[++top] = num;
for(int i = top; i > 0 && arr[i] < arr[i-1]; i--) {
int temp = arr[i];
arr[i] = arr[i-1];
arr[i-1] = temp;
}
printf("arr%d=%d", top, arr[top]);
}
关键点解析:
- 先将新数据加入数组末尾
- 使用插入排序方法,将新插入的数据调整到正确位置
- 打印输出当前插入的数据及其位置
3. GetMedian 函数
c
double GetMedian() {
if(top % 2 == 0)
return (double)arr[top/2];
else
return (arr[top/2] + arr[top/2+1]) / 2.0;
}
关键点解析:
- 通过判断top的奇偶性确定当前数组长度的奇偶性
- 奇数个元素时返回中间位置的元素
- 偶数个元素时返回中间两个数的平均值
- 使用2.0确保进行浮点数除法
复杂度分析
Insert 函数
- 时间复杂度:O(n),其中n为当前数组长度
- 空间复杂度:O(1),只需要常数级别的额外空间
GetMedian 函数
- 时间复杂度:O(1),直接访问数组元素
- 空间复杂度:O(1)
空间复杂度(整体)
- O(n),需要一个数组存储所有数据
注意事项
-
数组大小限制
- 需要确保不会超过1000个元素
- 实际应用中应考虑动态扩容
-
数值范围
- 确保输入的整数在int范围内
- 计算平均值时注意使用double避免精度损失
-
边界条件
- 处理第一个数据时的特殊情况
- 注意数组索引不要越界,基本上只要注意边界问题,插入排序整体上还是非常容易的