求数组的局部极小值和极大值

最近看到一个有意思的求数组局部极小值,极大值的代码,贴出来分享一下,源代码是matlab版的,我用我的较为暴力的诸多for循环将其修改为C++版的,不得不感叹matlab在矩阵运算上确实是很方便的!

局部极大值和极小值都能够求得,以代码中 Arr[NUM] = { 1.31,2.52, 2.52, 6.84, 5.48, 2.10, 6.77, 6.77, 1.22, 1.35,9.02 }为例,可以得到局部极大值三个,6.84, 6.77,9.02. 局部极小值三个:1.31,2.10,1.22.

如有错误,请指出,谢谢!

Matlab版,源版

%EXTREMA   Gets the global extrema points from a time series.
%   [XMAX,IMAX,XMIN,IMIN] = EXTREMA(X) returns the global minima and maxima
%   points of the vector X ignoring NaN‘s, where
%    XMAX - maxima points in descending order
%    IMAX - indexes of the XMAX
%    XMIN - minima points in descending order
%    IMIN - indexes of the XMIN
%
%   DEFINITION (from http://en.wikipedia.org/wiki/Maxima_and_minima):
%   In mathematics, maxima and minima, also known as extrema, are points in
%   the domain of a function at which the function takes a largest value
%   (maximum) or smallest value (minimum), either within a given
%   neighbourhood (local extrema) or on the function domain in its entirety
%   (global extrema).
%
%   Example:
%      x = 2*pi*linspace(-1,1);
%      y = cos(x) - 0.5 + 0.5*rand(size(x)); y(40:45) = 1.85; y(50:53)=NaN;
%      [ymax,imax,ymin,imin] = extrema(y);
%      plot(x,y,x(imax),ymax,‘g.‘,x(imin),ymin,‘r.‘)
%
%   See also EXTREMA2, MAX, MIN

%   Written by
%   Lic. on Physics Carlos Adri醤 Vargas Aguilera
%   Physical Oceanography MS candidate
%   UNIVERSIDAD DE GUADALAJARA
%   Mexico, 2004
%
%   [email protected]

% From       : http://www.mathworks.com/matlabcentral/fileexchange
% File ID    : 12275
% Submited at: 2006-09-14
% 2006-11-11 : English translation from spanish.
% 2006-11-17 : Accept NaN‘s.
% 2007-04-09 : Change name to MAXIMA, and definition added.

%**********尊重原创,以上是代码具体来源*****************

x=[1.31, 2.52, 2.52, 6.84, 5.48, 2.10, 6.77, 6.77, 1.22, 1.35];
xmax = [];
imax = [];
xmin = [];
imin = [];

% Vector input?
Nt = numel(x);
if Nt ~= length(x)
 error(‘Entry must be a vector.‘)
end

% NaN‘s:
inan = find(isnan(x));
indx = 1:Nt;
if ~isempty(inan)
 indx(inan) = [];
 x(inan) = [];
 Nt = length(x);
end

% Difference between subsequent elements:
dx = diff(x);

% Is an horizontal line?
if ~any(dx)
 return
end

% Flat peaks? Put the middle element:
a = find(dx~=0);              % Indexes where x changes
lm = find(diff(a)~=1) + 1;    % Indexes where a do not changes
d = a(lm) - a(lm-1);          % Number of elements in the flat peak
a(lm) = a(lm) - floor(d/2);   % Save middle elements
a(end+1) = Nt;

% Peaks?
xa  = x(a);             % Serie without flat peaks
b = (diff(xa) > 0);     % 1  =>  positive slopes (minima begin)
                        % 0  =>  negative slopes (maxima begin)
xb  = diff(b);          % -1 =>  maxima indexes (but one)
                        % +1 =>  minima indexes (but one)
imax = find(xb == -1) + 1; % maxima indexes
imin = find(xb == +1) + 1; % minima indexes
imax = a(imax);
imin = a(imin);

nmaxi = length(imax);
nmini = length(imin);                

% Maximum or minumim on a flat peak at the ends?
if (nmaxi==0) && (nmini==0)
 if x(1) > x(Nt)
  xmax = x(1);
  imax = indx(1);
  xmin = x(Nt);
  imin = indx(Nt);
 elseif x(1) < x(Nt)
  xmax = x(Nt);
  imax = indx(Nt);
  xmin = x(1);
  imin = indx(1);
 end
 return
end

% Maximum or minumim at the ends?
if (nmaxi==0)
 imax(1:2) = [1 Nt];
elseif (nmini==0)
 imin(1:2) = [1 Nt];
else
 if imax(1) < imin(1)
  imin(2:nmini+1) = imin;
  imin(1) = 1;
 else
  imax(2:nmaxi+1) = imax;
  imax(1) = 1;
 end
 if imax(end) > imin(end)
  imin(end+1) = Nt;
 else
  imax(end+1) = Nt;
 end
end
xmax = x(imax);
xmin = x(imin);

% NaN‘s:
if ~isempty(inan)
 imax = indx(imax);
 imin = indx(imin);
end

% Same size as x:
imax = reshape(imax,size(xmax));
imin = reshape(imin,size(xmin));

% Descending order:
[temp,inmax] = sort(-xmax);
clear temp
xmax = xmax(inmax);
imax = imax(inmax);
[xmin,inmin] = sort(xmin);
imin = imin(inmin);

C++版,较挫,for循环多,但是也能用

#include <iostream>
#include <vector>

using namespace std;

#define NUM 11
void main()
{
    float Arr[NUM] = { 1.31,2.52, 2.52, 6.84, 5.48, 2.10, 6.77, 6.77, 1.22, 1.35,9.02 };
    int num = NUM;
    float diff[NUM-1];
    vector <int> indexA, indexLm;
    //Difference between subsequent elements
    int n = 0;
    for (int i = 0; i < NUM - 1; i++)
    {
        diff[i] = Arr[i + 1] - Arr[i];
        if (diff[i] != 0)     indexA.push_back(i);  //元素发生变化
    }
    // Flat peaks? Put the middle element
    vector <int> diffIndexA;
    for (int i = 0; i < indexA.size()-1; i++)
    {
        int tmpdiff = indexA.at(i + 1) - indexA.at(i);
        if (tmpdiff != 1)   indexLm.push_back(i + 1);
    }
    vector <int> d;
    for (int i = 0; i < indexLm.size(); i++)
    {
        int index = indexLm.at(i);
        int tmp = indexA.at(index)-indexA.at(index-1);
        d.push_back(tmp);
    }
    for (int i = 0; i < d.size(); i++)
    {
        int lmValue = indexLm.at(i);
        int dvalue = d.at(i) / 2;
        int tmp = indexA.at(lmValue) - dvalue;
        indexA.at(lmValue) = tmp;
    }
    indexA.push_back(num-1);
    //Peak?
    vector <float> ArrIndexA;  //Seris without flat peaks
    for (int i = 0; i < indexA.size(); i++)
    {
        int tmpIndex = indexA.at(i);
        float value = Arr[tmpIndex];
        ArrIndexA.push_back(value);
    }
    vector <int> indexB;
    for (int i = 0; i < ArrIndexA.size()-1; i++)
    {
        float diff = ArrIndexA.at(i + 1) - ArrIndexA.at(i);
        if (diff>0)  indexB.push_back(1);  //1  positive slopes (minima begin)
        else indexB.push_back(0);   //0 negative slopes(maxima begin)
    }
    vector <int> xb;
    for (int i = 0; i < indexB.size()-1; i++)
    {
        int diff = indexB.at(i + 1) - indexB.at(i);
        xb.push_back(diff);   //-1 maxima indexes; 0 minima indexes
    }
    vector <int> imax, imin, max, min; //maxima indexes; minima indexes
    for (int i = 0; i < xb.size(); i++)
    {
        if (xb.at(i) == -1)   imax.push_back(i + 1);
        if (xb.at(i) == 1)    imin.push_back(i + 1);
    }
    for (int i = 0; i < imax.size(); i++)
    {
        int index = imax.at(i);
        int value = indexA.at(index);
        max.push_back(value);
    }
    for (int i = 0; i < imin.size(); i++)
    {
        int index = imin.at(i);
        int value = indexA.at(index);
        min.push_back(value);
    }
    int nmax = max.size();
    int nmin = min.size();
    //Maximum or minumin on a flat peak at the ends?
    vector <float> xmin, xmax;
    if (nmax == 0 && nmin == 0)
    {
        if (Arr[0]>Arr[num - 1])
        {
            xmax.push_back(Arr[0]);
            max.push_back(0);
            xmin.push_back(Arr[num - 1]);
            min.push_back(num - 1);
        }
        else if (Arr[0] < Arr[num - 1])
        {
            xmax.push_back(Arr[num - 1]);
            max.push_back(num - 1);
            xmin.push_back(Arr[0]);
            min.push_back(0);
        }

        return ;
    }
    //Maximum or minumin at the ends?
    if (0 == nmax)
    {
        max.push_back(0);
        max.push_back(num - 1);
    }
    else if (0 == nmin)
    {
        min.push_back(0);
        min.push_back(num - 1);
    }
    else
    {
        if (max.at(0) < min.at(0))
        {
            vector <int> tmp;
            tmp.swap(min);
            min.push_back(0);
            for (int i = 0; i < nmin; i++)
            {
                min.push_back(tmp[i]);
            }
        }
        else
        {
            vector <int>tmp;
            tmp.swap(max);
            max.push_back(0);
            for (int i = 0; i < nmax; i++)
            {
                max.push_back(tmp[i]);
            }
        }
        if (max.back()>min.back())
        {
            min.push_back(num - 1);
        }
        else
        {
            max.push_back(num - 1);
        }
    }
    for (int i = 0; i < max.size(); i++)
    {
        int index = max[i];
        float value = Arr[index];
        xmax.push_back(value);
    }
    for (int j = 0; j < min.size(); j++)
    {
        int index = min[j];
        float value = Arr[index];
        xmin.push_back(value);
    }

    //Descending Order,  bubble sort
    for (int j = 0; j < xmax.size()-1; j++)
    {
        for (int i = 0; i < xmax.size() - j -1; i++)
        {
            float tmp;
            if (xmax[i] < xmax[i + 1])
            {
                tmp = xmax[i];
                xmax[i] = xmax[i + 1];
                xmax[i + 1] = tmp;
            }
        }
    }

    system("pause");
}

时间: 2024-10-25 04:21:08

求数组的局部极小值和极大值的相关文章

写一个方法求数组中的最大值,最小值,总和以及平均值。

class Program { /// <summary> /// 求数组中的最大值,最小值,总和以及平均值. /// </summary> /// <param name="nums">输入一个数组</param> /// <returns>返回一个新的数组(max,min,sum,avg)</returns> public static int[] GetMaxMinSumAvg(int[] nums) { i

class 3 求数组中的最大值(单元测试)

1.问题引出: int Largest(int list[], int length) { int i,max; for(i = 0; i < (length – 1); i ++ ) { if(list[i] > max) { max=list[i]; } } return max; } 由此段程序编写一个正确的程序实现求数组的最大值. #include <iostream> using namespace std; int Largest(int list[],int leng

[LeetCode] Find Peak Element 求数组的峰值

A peak element is an element that is greater than its neighbors. Given an input array where num[i] ≠ num[i+1], find a peak element and return its index. The array may contain multiple peaks, in that case return the index to any one of the peaks is fi

《github一天一道算法题》:分治法求数组最大连续子序列和

看书.思考.写代码! /*************************************** * [email protected] * blog: http://blog.csdn.net/hustyangju * 题目:分治法求数组最大连续子序列和 * 思路:分解成子问题+合并答案 * 时间复杂度:O(n lgn) * 空间复杂度:O(1) ***************************************/ #include <iostream> using nam

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

1、打印二进制机器码,程序内存分析,大端序小端序,指针数组,数组指针,数组的三种访问方式,typedef,#if-0-#endif,求数组大小,括号表达式

 1.打印二进制机器码(分别表示32位的和64位的) #include <stdio.h> /*按照8位的长度打印一个数值*/ void dis8bit(char val) { int bit = 8; while(bit--) { if(1<<bit&val){ printf("1"); } else { printf("0"); } if(!(bit%4)) printf(" "); } putchar(1

用C随机产生的正整数存到数组中,并求数组中的所有元素最大值、最小值、平均值以及各元素之和,及第二大值。

用 C 求一组随机数的第二大值,不能通过对整体排序求得 1 随机产生20个[10 , 50]的正整数存到数组中,并求数组中的所有元素最大值.最小值.平均值以及各元素之和,及第二大值.        int a[20];    int sum = 0; //存储数组元素的和    //为数组赋值    printf("数组中的元素为:\n ");    for (int i = 0; i < 20; i ++) {        a[i] = arc4random() % 41 +

求数组中和为给定值的任意两个数

转载请注明出处:http://blog.csdn.net/ns_code/article/details/24933341     题目: 输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字.要求时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出任意一对即可. 例如输入数组1.2.4.7.11.15和数字15.由于4+11=15,因此输出4和11.     思路: 最直接的做法是暴力法,两个for循环,时间复杂度为O(n*n),但是这样没有充

已知一个数组,求数组中心元素

/** * */package Student_System;import java.util.*;import java.util.*;/**Homework11 * *Homework1101 *已知一个数组,求数组中心元素 * @author 读你一世 * * QQ: 1816274408 *2017年4月11日上午10:25:03 * */public class Homework1101 { public static void main(String[] args){ Scanner