एक वेक्टर को दो श्रेणियों में अवरोही क्रम में क्रमबद्ध करना


14

कहो कि मेरे पास पूर्णांक का वेक्टर है:

std::vector<int> indices;
for (int i=0; i<15; i++) indices.push_back(i);

फिर मैं इसे अवरोही क्रम में क्रमबद्ध करता हूं:

sort(indices.begin(), indices.end(), [](int first, int second) -> bool{return indices[first] > indices[second];})
for (int i=0; i<15; i++) printf("%i\n", indices[i]);

यह निम्नलिखित उत्पादन करता है:

14
13
12
11
10
9
8
7
6
5
4
3
2
1
0

अब मैं संख्या 3, 4, 5 और 6 को अंत तक ले जाना चाहता हूं, और उनके लिए अवरोही क्रम (अधिमानतः sortदूसरी बार उपयोग किए बिना ) रखना चाहता हूं । यानी, यहाँ वही है जो मैं चाहता हूँ:

14
13
12
11
10
9
8
7
2
1
0
6
5
4
3

मुझे std::sortइसे प्राप्त करने के लिए तुलनात्मक फ़ंक्शन को कैसे संशोधित करना चाहिए ?


4
return indices[first] > indices[second]क्या आपका मतलब नहीं है return first < second;?
acraig5075

2
एक सरल उतरते प्रकार के लिए, std::greaterसे <functional>अपने लैम्ब्डा के स्थान पर इस्तेमाल किया जा सकता। आपके प्रश्न के अनुसार, एक अधिक वर्बोज़ तुलनित्र लिखना जो आपके मूल्यों को सुनिश्चित करता है कि आप जिस तरह से चाहते हैं वह तुलना करना सबसे आसान तरीका है।
sweenish

4
@ acraig5075, अवरोही क्रम में यह होना चाहिए return first > second
ks1322

1
@ acraig5075 मुझे लगता है कि मुझे कुछ याद आ रहा है, या लोगों को आरोही और उतरते के बीच का अंतर नहीं पता है ?
sweenish

जवाबों:


8

आपका तुलनात्मक कार्य गलत है क्योंकि आप जो मान प्राप्त करते हैं firstऔर secondउसी के तत्व हैं std::vector। इसलिए, उन्हें सूचक के रूप में उपयोग करने की कोई आवश्यकता नहीं है। इसलिए, आपको बदलने की जरूरत है

return indices[first] > indices[second];

सेवा

return first > second;

अब, उस समस्या के बारे में जिसे आप हल करने का प्रयास करते हैं ...

आप अन्य तत्वों के साथ तुलना से 3, 4, 5 और 6 को छोड़ सकते हैं और फिर भी एक दूसरे से तुलना कर सकते हैं:

std::sort(
    indices.begin(), indices.end(),
    [](int first, int second) -> bool {
        bool first_special = first >= 3 && first <= 6;
        bool second_special = second >= 3 && second <= 6;
        if (first_special != second_special)
            return second_special;
        else
            return first > second;
    }
);

डेमो


@NutCracker हाँ, मैं मानता हूँ कि यह पहले शीर्ष मानदंड के लिए अच्छा है।
ढेर अतिप्रवाह

5

से कार्य मानक एल्गोरिदम पुस्तकालय की तरह iota, sort, find, rotateऔर copyअपने जीवन को आसान बना देगा। आपका उदाहरण नीचे आता है:

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <iterator>


int main()
{
  std::vector<int> indices(15);
  std::iota(indices.begin(), indices.end(), 0);
  std::sort(indices.begin(), indices.end(), std::greater<>());

  auto a = std::find(indices.begin(), indices.end(), 6);
  auto b = std::find(indices.begin(), indices.end(), 3);
  std::rotate(a, b + 1, indices.end());

  std::copy(indices.begin(), indices.end(), std::ostream_iterator<int>(std::cout, "\n"));
  return 0;
}

आउटपुट:

14
13
12
11
10
9
8
7
2
1
0
6
5
4
3


टिप्पणियों में @TedLyngmo अच्छी बात यह है कि इसके साथ सुधार किया जा सकता है:

auto a = std::lower_bound(indices.begin(), indices.end(), 6, std::greater<int>{});
auto b = a + 4;

auto b = a + 4;गलत है (यदि आप पिछले स्निपेट के साथ निरंतरता रखना चाहते हैं)। ऐसा auto b = a + 3;इसलिए होना चाहिए क्योंकि std::rotateआप उपयोग करते हैंb + 1
Biagio Festa

3

समाधान 1

एक गैर-रेखीय तुलनित्र के साथ सीधा दृष्टिकोण ।

inline constexpr bool SpecialNumber(const int n) noexcept {
  return n < 7 && 2 < n;
}

void StrangeSortSol1(std::vector<int>* v) {
  std::sort(v->begin(), v->end(), [](const int a, const int b) noexcept {
    const bool aSpecial = SpecialNumber(a);
    const bool bSpecial = SpecialNumber(b);

    if (aSpecial && bSpecial) return b < a;
    if (aSpecial) return false;
    if (bSpecial) return true;
    return b < a;
  });
}

समाधान २

std::algorithmएस (विभाजन) का उपयोग करना !

inline constexpr bool SpecialNumber(const int n) noexcept {
  return n < 7 && 2 < n;
}

void StrangeSortSol2(std::vector<int>* v) {
  auto pivot = std::partition(v->begin(), v->end(), std::not_fn(SpecialNumber));
  std::sort(v->begin(), pivot, std::greater{});
  std::sort(pivot, v->end(), std::greater{});
}

प्रदर्शन के विचार

ऐसा लग सकता है कि विभाजन के ऊपरी हिस्से के कारण दूसरा समाधान धीमा है। संभवतः यह नहीं है, क्योंकि आधुनिक प्रोसेसर में कैश और मिस-शाखा की भविष्यवाणी है।

बेंचमार्क


किसी भी अच्छे कंपाइलर को n <= 6 && 3 <= n टारगेट सीपीयू के लिए जो भी सबसे अच्छा काम करता है उसे बदलना चाहिए ताकि आप संख्या 2 और 7 को प्रस्तुत करके कुछ भी हासिल न कर सकें लेकिन संभावित भ्रम - और एक संदर्भ के बजाय वेक्टर को पॉइंटर क्यों लें?
टेड लिंग्गो

तर्क समारोह के रूप में `कास्ट इंट नम्बर` का उपयोग न करें
एंटोनी मोरियर

1
@AntoineMorrier क्यों?
ढेर ओवरफ्लो

@HeapOverflow क्योंकि यह कास्ट का उपयोग किए बिना समान है :)।
एंटोनी मॉरियर

@AntoineMorrier मुझे नहीं लगता कि यह समान है। क्या constपाठक यह नहीं बताता कि फ़ंक्शन मान नहीं बदलता है? वन-लाइनर के इस विशेष मामले में यह स्पष्ट हो सकता है, लेकिन सामान्य तौर पर यह नहीं है।
ढेर अतिप्रवाह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.