วิธีใช้ std :: sort เพื่อจัดเรียงอาร์เรย์ใน C ++


91

วิธีใช้ไลบรารีเทมเพลตมาตรฐานstd::sort()เพื่อจัดเรียงอาร์เรย์ที่ประกาศเป็น int v[2000];

C ++ มีฟังก์ชันบางอย่างที่สามารถรับดัชนีเริ่มต้นและสิ้นสุดของอาร์เรย์ได้หรือไม่

คำตอบ:


111

ใน C ++ 0x / 11 เราได้รับstd::beginและstd::endสิ่งที่มากเกินไปสำหรับอาร์เรย์:

#include <algorithm>

int main(){
  int v[2000];
  std::sort(std::begin(v), std::end(v));
}

หากคุณไม่มีสิทธิ์เข้าถึง C ++ 0x การเขียนด้วยตัวเองนั้นไม่ใช่เรื่องยาก:

// for container with nested typedefs, non-const version
template<class Cont>
typename Cont::iterator begin(Cont& c){
  return c.begin();
}

template<class Cont>
typename Cont::iterator end(Cont& c){
  return c.end();
}

// const version
template<class Cont>
typename Cont::const_iterator begin(Cont const& c){
  return c.begin();
}

template<class Cont>
typename Cont::const_iterator end(Cont const& c){
  return c.end();
}

// overloads for C style arrays
template<class T, std::size_t N>
T* begin(T (&arr)[N]){
  return &arr[0];
}

template<class T, std::size_t N>
T* end(T (&arr)[N]){
  return arr + N;
}

12
มีstd::begin()และstd::end()เพิ่มเติม c ++ 1x? มันดีมาก - น่าจะเป็นแบบนี้ตั้งแต่แรกแล้วมันจะทำให้อัลกอริทึมทั่วไปมากขึ้น!
j_random_hacker

10
std::begin()และstd::end()ไม่ได้เป็นส่วนหนึ่งของมาตรฐาน C ++ ปัจจุบัน แต่คุณสามารถใช้boost::begin()และboost::end().
Kirill V. Lyadvinsky

1
แก้ไขตามความคิดเห็น
Xeo

2
เพียงแค่เตือนความจำ: นานก่อนที่พวกเขาจะเสนอ C ++ 11 พวกเราส่วนใหญ่มี a beginและendฟังก์ชันดังกล่าวในชุดเครื่องมือส่วนตัว อย่างไรก็ตามก่อน C ++ 11 พวกเขามีข้อเสียของ serios: ไม่ได้ส่งผลให้เกิดนิพจน์คงที่ sizeofดังนั้นขึ้นอยู่กับความต้องการเฉพาะที่เราต้องการใช้พวกเขาหรือแมโครที่ทำส่วนของทั้งสอง
James Kanze

1
@Xeo ฉันไม่แน่ใจว่าฉันเข้าใจที่คุณพูด decltypeทำให้การใช้งานบางอย่างง่ายขึ้นอย่างแน่นอน แต่ฉันไม่เห็นว่ามันเกี่ยวข้องกับฟังก์ชันฟรีbeginและendอะไร (และจริงๆแล้วคุณควรมีสองอันอันหนึ่งสำหรับอาร์เรย์สไตล์ C และอีกอันสำหรับคอนเทนเนอร์ที่มีการเลือกปฏิบัติโดยอัตโนมัติดังนั้นคุณจึงสามารถใช้มันในเทมเพลตโดยไม่รู้ว่าประเภทนั้นเป็นคอนเทนเนอร์หรืออาร์เรย์สไตล์ C)
James Kanze

71
#include <algorithm>
static const size_t v_size = 2000;
int v[v_size];
// Fill the array by values
std::sort(v,v+v_size); 

ในC ++ 11 :

#include <algorithm>
#include <array>
std::array<int, 2000> v;
// Fill the array by values
std::sort(v.begin(),v.end()); 

5
+1: ถูกต้อง แต่เปราะมาก หากการจัดเรียงไม่อยู่ใกล้กับการประกาศสิ่งนี้สามารถแตกหักได้ง่ายระหว่างการบำรุงรักษา
Martin York

1
@ มาร์ติน: จริง std::vectorนั่นเป็นเหตุผลที่ฉันชอบที่จะใช้ รหัสของฉันคือ:std::vector<int> v(2000); std::sort( v.begin(), v.end() );
Naszta

2
แน่นอนว่าการใช้ขนาดอาร์เรย์ตามตัวอักษรเป็นสิ่งที่อันตรายเสมอดังตัวอย่าง แต่ไม่มีอะไรผิดปกติกับการใส่ขนาดอาร์เรย์เป็น 'const int'
Kai Petzke

31

หากคุณไม่ทราบขนาดคุณสามารถใช้:

std::sort(v, v + sizeof v / sizeof v[0]);

แม้ว่าคุณจะทราบขนาด แต่คุณควรเขียนโค้ดด้วยวิธีนี้เนื่องจากจะช่วยลดความเป็นไปได้ของข้อผิดพลาดหากขนาดอาร์เรย์มีการเปลี่ยนแปลงในภายหลัง


3
หากมีการจัดสรรแบบคงที่เขาควรรู้ขนาดเพราะคอมไพเลอร์รู้ แต่นี่เป็นการฝึกเขียนโค้ดที่ดีกว่า
Benoit

7
เนื่องจากคุณกำลังเขียนรหัสพิสูจน์ในอนาคตแทนที่จะใช้sizeof x/sizeof *xเคล็ดลับคุณควรใช้เทมเพลตที่ปลอดภัยกว่า: template <typename T, int N> int array_size( T (&)[N] ) { return N; }เนื่องจากจะล้มเหลวหากแทนที่จะเป็นอาร์เรย์ที่คุณส่งตัวชี้ สามารถแปลงเป็นค่าคงที่ของเวลาในการคอมไพล์ได้หากจำเป็น แต่การอ่านความคิดเห็นนั้นยากเกินไปเล็กน้อย
David Rodríguez - น้ำลายไหล

1
@David: ความคิดที่ดี แต่วิธีที่ดียิ่งขึ้น (และกล้าพูดว่าถูกต้อง) คือการกำหนดbegin()และend()ทำหน้าที่แม่แบบที่มีความเชี่ยวชาญสำหรับคอนเทนเนอร์ทั่วไปทุกประเภทรวมถึงอาร์เรย์และใช้แทน คำตอบของ Xeo ทำให้ฉันคิดว่าสิ่งเหล่านี้ถูกเพิ่มลงใน C ++ แล้วตอนนี้ดูเหมือนว่าพวกเขายังไม่ได้ ... ฉันจะดูว่าคนอื่นพูดอะไรแล้วอัปเดต
j_random_hacker

1
:) ฉันมีส่วนหัวของยูทิลิตี้ขนาดเล็กที่มีไม่กี่บิตเช่นนี้รวมทั้งbegin, end, size, STATIC_SIZE(มาโครที่ให้ผลตอบแทนคงที่รวบรวมเวลาที่มีขนาด) แต่จะซื่อสัตย์ฉันแทบจะไม่เคยใช้นอกตัวอย่างโค้ดขนาดเล็กที่
David Rodríguez - dribeas

1
ขนาดของอาร์เรย์สามารถรับได้std::extent<decltype(v)>::valueใน C ++ 11
xis

18

คุณสามารถจัดเรียงได้ std::sort(v, v + 2000)


4
+1: ถูกต้อง แต่เปราะมาก หากการจัดเรียงไม่อยู่ใกล้กับการประกาศสิ่งนี้สามารถแตกหักได้ง่ายระหว่างการบำรุงรักษา
Martin York

3
//It is working
#include<iostream>
using namespace std;
void main()
{
    int a[5];
    int temp=0;
    cout<<"Enter Values"<<endl;
    for(int i=0;i<5;i++)
    {
        cin>>a[i];
    }
    for(int i=0;i<5;i++)
    {
        for(int j=0;j<5;j++)
        {
            if(a[i]>a[j])
            {
                temp=a[i];
                a[i]=a[j];
                a[j]=temp;
            }
        }
    }
    cout<<"Asending Series"<<endl;
    for(int i=0;i<5;i++)
    {
        cout<<endl;
        cout<<a[i]<<endl;
    }


    for(int i=0;i<5;i++)
    {
        for(int j=0;j<5;j++)
        {
            if(a[i]<a[j])
            {
                temp=a[i];
                a[i]=a[j];
                a[j]=temp;
            }
        }
    }
    cout<<"Desnding Series"<<endl;
    for(int i=0;i<5;i++)
    {
        cout<<endl;
        cout<<a[i]<<endl;
    }


}

2

คุณสามารถใช้ sort () ใน C ++ STL sort () ฟังก์ชันไวยากรณ์:

 sort(array_name, array_name+size)      

 So you use  sort(v, v+2000);

2

มันง่ายอย่างที่คิด ... C ++ ให้ฟังก์ชันใน STL (ไลบรารีเทมเพลตมาตรฐาน) ที่เรียกว่าsortซึ่งทำงานเร็วกว่าการเรียงลำดับด่วนด้วยรหัสมือ 20% ถึง 50%

นี่คือโค้ดตัวอย่างสำหรับการใช้งาน:

std::sort(arr, arr + size);

1

การเรียงลำดับ C ++ โดยใช้ฟังก์ชันการเรียงลำดับ

#include <bits/stdc++.h>
 using namespace std;

vector <int> v[100];

int main()
{
  sort(v.begin(), v.end());
}

อันนี้ใช้ได้กับรุ่นเก่ากว่า ฉันลองแล้ว:std::sort(arr, arr + arr_size)
Code Cooker

นี่ใช้ไม่ได้เลย ไม่ต้องบอกว่ามันไม่ใช่ C ++
LF


1
//sort by number
bool sortByStartNumber(Player &p1, Player &p2) {
    return p1.getStartNumber() < p2.getStartNumber();
}
//sort by string
bool sortByName(Player &p1, Player &p2) {
    string s1 = p1.getFullName();
    string s2 = p2.getFullName();
    return s1.compare(s2) == -1;
}

ยินดีต้อนรับสู่ Stack Overflow คำตอบที่ให้เฉพาะรหัสโดยไม่มีคำอธิบายใด ๆ มักจะขมวดคิ้วโดยเฉพาะอย่างยิ่งเมื่อ a) มีคำตอบมากมายที่ให้ไว้แล้วและ b) คำตอบได้รับการยอมรับแล้ว โปรดอธิบายให้ละเอียดว่าเหตุใดโซลูชันของคุณจึงแตกต่างและ / หรือดีกว่าจาก 12 ข้อที่เคยโพสต์ไว้
chb

1

ด้วยไลบรารี Ranges ที่มาใน C ++ 20 คุณสามารถใช้

ranges::sort(arr);

โดยตรงarrอาร์เรย์ในตัวอยู่ที่ไหน


0

วิธีการเรียงลำดับโดยไม่ต้องstd::sort:

// sorting myArray ascending
int iTemp = 0;
for (int i = 0; i < ARRAYSIZE; i++)
{
    for (int j = i + 1; j <= ARRAYSIZE; j++)
    {
        // for descending sort change '<' with '>'
        if (myArray[j] < myArray[i])
        {
            iTemp = myArray[i];
            myArray[i] = myArray[j];
            myArray[j] = iTemp;
        }
    }
}

เรียกใช้ตัวอย่างที่สมบูรณ์:

#include <iostream> // std::cout, std::endl /* http://en.cppreference.com/w/cpp/header/iostream */
#include <cstdlib>  // srand(), rand()      /* http://en.cppreference.com/w/cpp/header/cstdlib */
#include <ctime>    // time()               /* http://en.cppreference.com/w/cpp/header/ctime */


int main()
{
    const int ARRAYSIZE = 10;
    int myArray[ARRAYSIZE];

    // populate myArray with random numbers from 1 to 1000
    srand(time(0));
    for (int i = 0; i < ARRAYSIZE; i++)
    {
        myArray[i] = rand()% 1000 + 1;
    }

    // print unsorted myArray
    std::cout << "unsorted myArray: " << std::endl;
    for (int i = 0; i < ARRAYSIZE; i++)
    {
        std::cout << "[" << i << "] -> " << myArray[i] << std::endl;
    }
    std::cout << std::endl;

    // sorting myArray ascending
    int iTemp = 0;
    for (int i = 0; i < ARRAYSIZE; i++)
    {
        for (int j = i + 1; j <= ARRAYSIZE; j++)
        {
            // for descending sort change '<' with '>'
            if (myArray[j] < myArray[i])
            {
                iTemp = myArray[i];
                myArray[i] = myArray[j];
                myArray[j] = iTemp;
            }
        }
    }

    // print sorted myArray
    std::cout << "sorted myArray: " << std::endl;
    for (int i = 0; i < ARRAYSIZE; i++)
    {
        std::cout << "[" << i << "] -> " << myArray[i] << std::endl;
    }
    std::cout << std::endl;

    return 0;
}

1
จริงๆ? คุณต้องการใช้การจัดเรียงฟองแบบช้าๆแทนไลบรารีมาตรฐานหรือไม่? ไม่เพียงแค่นั้นคุณยังมีข้อผิดพลาดแบบ off-by-one ที่ทำให้เกิด UB
Mark Ransom

-1

คุณสามารถใช้ได้,

 std::sort(v.begin(),v.end());

สวัสดีคำถามนี้ดูเหมือนจะมีคำตอบที่ยอมรับในวงกว้างแล้ว คุณอธิบายได้ไหมว่าสิ่งนี้แตกต่างกันอย่างไร?
Stefan

อาร์เรย์ไม่มีbeginและendวิธีการ คุณต้องนึกถึงไฟล์vector.
Mark Ransom
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.