Ищем алгоритм поиска в обоих направлениях - c / c ++ / awk

0

Я работаю над некоторым вычислительным моделированием, в котором мне нужно искать данные с нерегулярным интервалом и данные не сортируются, так что вот сценарий

Мои контрольные точки

col1 col2 
1    92
9    45
7    22
2    14
5    10

Таким образом, алгоритм поиска, который я ищу, выглядит следующим образом:

скажем, если key = 2 то функция должна вернуть индекс 2 с момента его появления, скажем, например, я хочу искать 3, его нет в col1, так как его недоступно, мне нужно найти ближайшее значение в обоих направлениях, которое является индексом 2 и 5

в случае awk точный ключ можно найти, используя что-то вроде этого

  function search(Arr,key){
                             if((key in Arr))
                              return key
                          }

Но я действительно не знаю, но поиск ближайшего значения как в верхнем, так и в нижнем направлении, в случае, если точный ключ не найден

Я надеюсь, что мое требование будет ясным, в случае отрицательного голосования, пожалуйста, добавьте свой комментарий, так как моя проблема связана с меньшей репутацией (новичок в этом форуме), я не могу проголосовать за полезные ответы, пожалуйста, сотрудничайте.

  • 1
    Вы пытались отсортировать массив и затем использовать Binary Search как это может дать вам как верхнее, так и нижнее значение.
  • 1
    Делать это в оболочке или в AWK будет сложно, если вы не прочитаете файл, как в программе на C или C ++. В C это не слишком сложно, а в C ++ это просто. Однако никто, вероятно, не даст вам полного решения (которое будет сильно отличаться в зависимости от используемого языка), если вы не приложите усилий, чтобы показать, что вы уже пробовали.
Показать ещё 4 комментария
Теги:
awk

3 ответа

2
Лучший ответ

Поскольку вы не отсортированы, лучше всего искать точные, нижние и верхние одновременно, чтобы перебирать данные только один раз.

#include <iostream>
#include <vector>
#include <utility>

using Samples = std::vector<std::pair<int,int>>;

Samples::const_iterator Find( Samples const & samp_, int val_, Samples::const_iterator & prev_, Samples::const_iterator & next_ ) {
    auto end = std::end(samp_);
    auto lower = end;
    auto upper = end;
    auto it = begin(samp_);
    for( ; it!=end; ++it) {
        if ( it->first == val_ )
            return it;
        if ( it->first < val_ && ( lower == end || lower->first < it->first ) )
            lower = it;
        else if ( it->first > val_ && ( upper == end || upper->first > it->first ) )
            upper = it;
    }
    prev_ = lower;
    next_ = upper;
    return end;
}

std::ostream & operator<<( std::ostream & os, std::pair<int,int> const & p ) {
    return os << "( " << p.first << ", " << p.second << " )";
}

int main() {
    Samples samps { {1,92}, {9,45},{7,22},{2,14},{5,10} };

    auto test = [&] ( int v ) {
        Samples::const_iterator lower;
        Samples::const_iterator upper;
        auto result = Find( samps, v, lower, upper );
        if ( result != end( samps ) ) {
            std::cout << "found " << *result << std::endl;
        } else {
            std::cout << "not found ";
            if ( lower  != end( samps ) )
                std::cout << "lower is " << *lower;
            else 
                std::cout << "no lower";
            if ( upper  != end( samps ) )
                std::cout << " upper is " << *upper;
            else 
                std::cout << " no upper";
            std::cout << std::endl; 
        }
    };
    test(2);
    test(3);
    test(12);
    test(-1);
}

И результат:

found ( 2, 14 ) 
not found lower is ( 2, 14 ) upper is ( 5, 10 ) 
not found lower is ( 9, 45 ) no upper
not found no lower upper is ( 1, 92 )
  • 0
    Вы действительно программист высшего класса, я действительно не знаю, сколько недель / месяцев я потрачу, чтобы преобразовать ваш код c ++ в c. Можете ли вы оставить комментарий в своем коде? так что мне будет легко преобразовать его в
  • 0
    просто замените итераторы и auto на индексы int, begin - 0, end - -1, вектор пары - это массив C структурной пары с членами tko, pair samps[N]; и вы перебираете массив с индексами от 0 до размера.
Показать ещё 3 комментария
3

Раствор оболочки,

perl -lane'
BEGIN{ $k=pop }
push @r, [@F];
END { 
  for (sort{ $a->[0] <=> $b->[0] } @r) {
    $v= $_->[0] <=> $k;
    $h{$v} = $_->[1];
    last if $v >0;    
  }
  print join " ", ($h{0} or @h{-1,1});
}
' file 3

вывод

14 10
2

В Gnu Awk версии 4 вы можете использовать PROCINFO["sorted_in"] например:

gawk -vkey=7 -f a.awk file

где a.awk:

{
    a[$1]=$2
}
END {
    if (key in a)
        print "Found key "key" with value "a[key]
    else {
        PROCINFO["sorted_in"]="@ind_num_asc"
        for (i in a) {
            if (i+0>key) { k=i; break}
            j=i
        }
        if (j)  
            print "Prev key: "j
        if(k)
            print "Next key: "k
    }
}

Вывод:

$gawk -vkey=6 -f a.awk file

Prev key: 5
Next key: 7

$gawk -vkey=5 -f a.awk file

Found key 5 with value 10

Ещё вопросы

Сообщество Overcoder
Наверх
Меню