刚才刷手机看到今天脚本之家推送的一个文章《模拟管道算法的一次实际应用》 地址 https://mp.weixin.qq.com/s/89VfbuuB3Yz8sQFv2JwMYA
作者对问题的描述是 “”“
前段时间从事单片机开发的同学找我帮忙解决一个问题:有一个数据采集的设备,该设备定时对外进行数据采集。当数据采集小于5份时,记住所有的数据,并求和;
当数据采集超过5份时,只记住最近采集到的5份,并求和。
”“”
作者使用了顺序前移法,每次向后插入一个数据都需要把n-1个数据向前移动一次。那么问题来了,对于单片机来说其速度是硬伤(虽然也占用不了多少时间),可是总还是不优雅。此外,
如果对于具有1000个数据的情形是否还能这样靠移动呢? 分析一下这样移动的时间复杂度就是O(n)。
其实,我们还有更好的方法,可以让时间复杂度成为O(1)。使用什么方法呢,当然使用指针,移动指针,代码清晰简单,也无需过多解释:
#include <iostream> using namespace std; static const uint16_t DATALENGTH=5; //数据长度 static uint16_t datalist[DATALENGTH]={0}; static uint16_t *currentdata=datalist; //这里当成一个圈,从头开始插入,当最后一个插入后,下一次从头再来 void adddata(uint16_t dt) { *currentdata++=dt; if (currentdata==datalist+DATALENGTH) currentdata=datalist; //这里就是负责当插入的指针到末尾后,跳回到前面 } void printdata() { for (int i=0;i<DATALENGTH;i++){ cout<<datalist[i]<<' '; } cout<<endl; } void calsum() { uint32_t sum=0; for (int i=0;i<DATALENGTH;i++){ sum+=datalist[i]; } cout<<"The sum of sensor is :"<<sum <<endl; } int main() { uint16_t dt; while(1) { printdata(); cin>>dt; adddata(dt); calsum(); } return 0; }
输出:
0 0 0 0 0
1
The sum of sensor is :1
1 0 0 0 0
2
The sum of sensor is :3
1 2 0 0 0
3
The sum of sensor is :6
1 2 3 0 0
4
The sum of sensor is :10
1 2 3 4 0
5
The sum of sensor is :15
1 2 3 4 5
6
The sum of sensor is :20
6 2 3 4 5
7
The sum of sensor is :25
6 7 3 4 5
8
The sum of sensor is :30
6 7 8 4 5
9
The sum of sensor is :35
6 7 8 9 5
0
The sum of sensor is :30
6 7 8 9 0
这不是更清晰简单吗?
这里我想说的是,作者的想法没有问题但是如果数据很长的话,那就不是一个好的方法了。
我们有时候需要对问题真的做好分析,找到那个hit point。
不要说我太mean,有时候需要较较真。这个方法可能我自己也要使用。
看到数据结构,就是个头尾相接的链表,总之,这是一个数据结构问题。
还有,一般加和是不怎么用的,需要滤波是真的,中值滤波可以考虑下。
当然本文的算法即使数据长度修改为1000,10000。 插入新的数据仍然嗖的一下。因为时间复杂度是O(1)。
如果使用Python 那就更简单了。直接使用:
from collections import deque
dt=deque(maxlen=5) #maxlen指的是长度
dt.append(1) #向右添加元素
dt.append(2)
dt.append(3)
dt.append(4)
dt.append(5)
deque([1, 2, 3, 4, 5], maxlen=5)
dt.append(6)
deque([2, 3, 4, 5, 6], maxlen=5)
python还是很神奇。