Hi everyone, I'm trying to sort data coming in real time from my sensor with the library <ArduinoSort.h> but I'm having issues.
In my sketch for example, I want to sort every n values (600 in this case) and just display the last value (n-1), the biggest value as they are sorted in ascending order. The data are coming in real time and I just display the biggest value of every n values.
#define pinn 34
#include <ArduinoSort.h>
int* myArray;
int piezo = 0;
int n = 600;
void setup()
{
Serial.begin(115200);
}
void loop()
{
for(int i = 0; i < n; i++)
{
piezo = analogRead(pinn);
myArray[i] = piezo;
sortArray(myArray, n);
printArray("sortArray:", myArray);
int biggest = myArray[n-1];
Serial.print("Biggest: ");
Serial.println(biggest);
}
}
void printArray(String msg, int* myArray)
{
Serial.println(msg);
Serial.println(myArray[n-1]);
}
Declaring the array as a pointer then stuffing 600 int values in it which take at least 1200 bytes, maybe more depending on the board being used, does not sound like a very smart thing to do
Which board are you using ?
Why bother with the array when you can determine the highest of the 600 values as you read them ?
#define N 600
int myArray [N];
void loop()
{
int max = myArray [0];
for(int i = 0; i < N; i++)
{
if (max < myArray [i])
max = myArray [i];
}
Serial.print("Biggest: ");
Serial.println(max);
}
It seems you are running your code on a ESP32 MCU so maybe you could have advantage using a std::set or std:map or one of the other available STL "containers".
myArray is a pointer to some random place in memory, that is never initiaized, and NEVER points to ANY allocated memory! You are scribbling all over memory! You need to create the actual array, or use malloc() to allocate memory for the array.
You don't need to store or sort anything to do that.
As they come in, keep track of the highest one, and what number that one was if the number in the group of 600 is important.
int largestSeen = -32767; // initial smallest possible number
int position = -1; // at no position
// later as they come in being counted
if (newValue > largestSeen) }
largestSeen = newValue;
position = countOfItems;
}
// when countOfItems is N, you have largestSeen, and where.
// reset and repeat
If position stays at -1 it must mean all N values were -32767.
You don't need to sort. But, it sounds like OP wants to know the maximum value in a sliding window of the most recent 600 samples. Thus, you do have to keep all 600. Every time a new sample enters the the window, one leaves the window. So, you need to check for a new maximum on every iteration.
A bit of googling sez to me that this is a popular interview question.
No solution I have found has been described in the straightforward manner of @PaulRB in #11.
I go in and out of understanding and accepting the offered algorithm as valid and correct, which makes me very glad I am way past school's out forever.
I will however enjoy convincing myself somehow, at my own pace and with my own methods.
An array is a poor data structure to use for this (if indeed you want them all sorted.)
Even with an array, adding a new value to a sorted list is much easier than re-sorting the entire array.
Finding the maximum value in an array is much easier than sorting the entire array.
Some sorting algorithms (notable quicksort, IIRC) do especially poorly if the input is already "mostly sorted."
If you're wanting the max of the most recent N values (as per #10, #11), you have to keep the array in "as received" order (so that you know which elements to discard as new data comes in), so the original proposal to sort the array each time wouldn't work at all.
Finding the largest elements of a much larger set of data points is a somewhat interesting problem. I wrote some code to score gymnastics meets once (in Fortran!), and it kept track of the top 6 scores (the "medalists.") I ended up popping each score into a bubble-sort of the top 6 values, reducing (I think?) the complexity from NN to ~N6, which was "good enough."