C语言常用算法

 目录

一、冒泡排序

二、平均滤波

1.中位值平均滤波法

2.递推平均滤波法

3.算术平均滤波法


一、冒泡排序

1.定义

重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来,直重复这个过程,直到没有任何两个相邻元素可以交换,就表明完成了排序。

假设需要排列的数组为a[4]={7,23,6,8}

用冒泡排序对这四个数排序,需要进行(4-1)轮比较,每轮都对相邻的两个元素进行排序。第一轮可以将最大元素,并入已排序序列中;第一轮可以将第二大元素,并入已排序序列中;以此类推,直到待排序序列中仅剩 1 个元素,无论再进行相邻元素的比较,因此直接将其并入已排序序列中。

例:

#include <stdio.h>
//交换 a 和 b 的位置的函数
#define N 5
int a[N] = { 5,1,4,2,8 };
void swap(int *a, int *b);
//这是带输出的冒泡排序实现函数,从输出结果可以分析冒泡的具体实现流程
void BubSort_test();
//这是不带输出的冒泡排序实现函数,通过此函数,可直接对数组 a 中元素进行排序
void BubSort_pro();
int main()
{
    BubSort_test();
    return 0;
}
void swap(int *a, int *b) {
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

//这是带输出的冒泡排序实现函数,从输出结果,可以看到冒泡的具体实现流程
void BubSort_test() {
    for (int i = 0; i < N; i++) {
        //对待排序序列进行冒泡排序
        for (int j = 0; j + 1 < N - i; j++) {
            //相邻元素进行比较,当顺序不正确时,交换位置
            if (a[j] > a[j + 1]) {
                swap(&a[j], &a[j + 1]);
            }
        }
        //输出本轮冒泡排序之后的序列
        printf("第%d轮冒泡排序:", i + 1);
        for (int i = 0; i < N; i++) {
            printf("%d ", a[i]);
        }
        printf("\n");
    }
}

//这是不带输出的冒泡排序实现函数,通过此函数,可直接对数组 a 中元素进行排序
void BubSort_pro() {
    for (int i = 0; i < N; i++) {
        //对待排序序列进行冒泡排序
        for (int j = 0; j + 1 < N - i; j++) {
            //相邻元素进行比较,当顺序不正确时,交换位置
            if (a[j] > a[j + 1]) {
                swap(&a[j], &a[j + 1]);
            }
        }
    }
}
运行结果为:

第1轮冒泡排序:1 4 2 5 8
第2轮冒泡排序:1 2 4 5 8
第3轮冒泡排序:1 2 4 5 8
第4轮冒泡排序:1 2 4 5 8
第5轮冒泡排序:1 2 4 5 8

二、平均滤波

1.中位值平均滤波法

说明:中位值滤波算法特别适用于会偶然出现异常值的系统。

优点:相比于平均值滤波算法,中位值滤波算法能够有效滤除偶然的脉冲干扰。

缺点:与平均值滤波算法相同,中位值滤波算法也存在反应速度慢、滞后的问题。

方法①

1、连续采样N次(N取奇数)
2、把N次采样值按大小排列(多采用冒泡法)
3、去掉最大最小值取平均值为本次有效值

float data[10];
 
float middleFilter(float in_data)
{
    float sum = 0;
    float temp[10];
    float change;
    int i,j;
    //记录数据
    for(i=0; i<9; i++)
    {
        data[i]=data[i+1];
    }
    data[9] = in_data;
    //复制数据
    for(i=0; i<10; i++)
        temp[i] = data[i];
    //冒泡法排序
    for(i=1; i<10; i++)
        for(j=0; j<10-i; j++)
        {
            if(temp[j] > temp[j+1])
            {
                change = temp[j];
                temp[j] = temp[j+1];
                temp[j+1] = change;
            }
        }
    //求和
    for(i=2; i<9; i++)
        sum = sum + temp[i];
    //返回平均值
    return(sum/8);
}

方法②

1.找出最大最小值

2.去掉最小最大值

3.求平均值

void MindiaValnafiltering(u16 *buf,u8 len)
{
    unsigned short int max,min;
    unsigned short long sum;
    unsigned char i;
    max=buf[0];
    min=max;
    sum=max+((len-2)>>1)
    for(i=1;i<len;i++)
    {
        if(max<buf[i]) max=buf[i];
        if(min>buf[i]) min=buf[i];
        sum=sum+buf[i];
    }
    return MindiaVal=(sum-max-min)/(len-2)
}

下面比较一下中值滤波和算术平均值滤波的差异

红色曲线为中值滤波后的曲线

 红色曲线为算术平均滤波后的曲线

2.递推平均滤波法(又称滑动平均滤波法)

队列定义:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。

方法

1、把连续取N个采样值看成一个队列,队列的长度固定为N
2、每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则)
3、把队列中的N个数据进行算术平均运算,就可获得新的滤波结果(以保证队列中的N个数据都为最新数据
4、N值的选取:流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4;

优点:

1、对周期性干扰有良好的抑制作用
2、平滑度高

缺点:

1、灵敏度低
2、对偶然出现的脉冲性干扰的抑制作用较差
3、不易消除由于脉冲干扰所引起的采样值偏差
4、不适用于脉冲干扰比较严重的场合
5、比较浪费RAM 

#define TARGET_tYPE int
 
#define N 8
 
//队列
TARGET_tYPE value_buf[N];
 
//初始化队列
void Init_Queue()
{
    for(int i = 0; i < N; i++)
    {
        value_buf[i] = 0;
    }
}
 
//插入队列
void Add_Queue(TARGET_tYPE value)
{
    //数组元素右移
    for(int i = N-1; i > 0; i--)
    {
        value_buf[i] = value_buf[i-1];
    }
    //插入新元素
    value_buf[0] = value;
}
 
//求队列和
TARGET_tYPE Sum_Queue()
{
    TARGET_tYPE ADDER = 0;
    for(int i = 0; i < N; i++)
    {
        ADDER = ADDER + value_buf[i];
    }
    return ADDER;
}
 
TARGET_tYPE Smoothing_arithmetic_mean_FILTER()
{
    //采集数据插入队列
    Add_Queue(get_data());
    
    return Sum_Queue()/N;
}  

3.算术平均滤波法

方法

1、连续取N个采样值进行算术平均运算
2、N值较大时:信号平滑度较高,但灵敏度较低
3、N值较小时:信号平滑度较低,但灵敏度较高
4、N值的选取:一般流量,N=12;压力:N=4;

优点:

对滤除混杂在被测信号上的随机干扰信号非常有效。这样信号的特点是有一个平均值,信号在某一数值范围附近上下波动

缺点:

1、不易消除脉冲干扰引起的误差。
2、对于采样速度较慢或要求数据更新率较高的实时控制不适用
3、比较浪费RAM   

#define N 12

char value_buf[N];

char i=0;

char filter()

{

char cnt;

int  sum=0;

value_buf[i++] = get_ad();

if ( i == N )   i = 0;

for ( cnt=0;cnt < N-1;cnt++)

sum = value_buf[cnt];

return (char)(sum/N);

}

  • 4
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值