Quickly find whether a value is present in a C array?

前端 未结 15 1301
灰色年华
灰色年华 2021-01-29 17:30

I have an embedded application with a time-critical ISR that needs to iterate through an array of size 256 (preferably 1024, but 256 is the minimum) and check if a value matches

15条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-29 18:04

    You're asking for help with optimising your algorithm, which may push you to assembler. But your algorithm (a linear search) is not so clever, so you should consider changing your algorithm. E.g.:

    • perfect hash function
    • binary search

    Perfect hash function

    If your 256 "valid" values are static and known at compile time, then you can use a perfect hash function. You need to find a hash function that maps your input value to a value in the range 0..n, where there are no collisions for all the valid values you care about. That is, no two "valid" values hash to the same output value. When searching for a good hash function, you aim to:

    • Keep the hash function reasonably fast.
    • Minimise n. The smallest you can get is 256 (minimal perfect hash function), but that's probably hard to achieve, depending on the data.

    Note for efficient hash functions, n is often a power of 2, which is equivalent to a bitwise mask of low bits (AND operation). Example hash functions:

    • CRC of input bytes, modulo n.
    • ((x << i) ^ (x >> j) ^ (x << k) ^ ...) % n (picking as many i, j, k, ... as needed, with left or right shifts)

    Then you make a fixed table of n entries, where the hash maps the input values to an index i into the table. For valid values, table entry i contains the valid value. For all other table entries, ensure that each entry of index i contains some other invalid value which doesn't hash to i.

    Then in your interrupt routine, with input x:

    1. Hash x to index i (which is in the range 0..n)
    2. Look up entry i in the table and see if it contains the value x.

    This will be much faster than a linear search of 256 or 1024 values.

    I've written some Python code to find reasonable hash functions.

    Binary search

    If you sort your array of 256 "valid" values, then you can do a binary search, rather than a linear search. That means you should be able to search 256-entry table in only 8 steps (log2(256)), or a 1024-entry table in 10 steps. Again, this will be much faster than a linear search of 256 or 1024 values.

提交回复
热议问题