Quicksort วนซ้ำไม่สิ้นสุดหากมีค่าซ้ำกัน

ฉันมีโปรแกรม Quicksort ที่ใช้งานได้ดีจนกระทั่งฉันพยายามเรียงลำดับอาร์เรย์ที่มีตัวเลขซ้ำกัน โปรแกรมติดอยู่ในวงวนไม่สิ้นสุด ฉันเชื่อว่าสิ่งนี้เกิดขึ้นในบล็อก While(lower < upper) ของโค้ด

void quickSort(int array[], int size){
  if(size < 2) return;

  int pivot, lower, upper, temp;

  //Set the indeces for the first and last elements                                 
  lower = 0;
  upper = size - 1;

  //Select pivot element randomly                                                   
  pivot = array[rand() % (size)];                                                                                                     

  while(lower < upper){
    //Lower must be a number < than pivot and upper a number >= pivot               
    while(array[lower] < pivot){
      lower++;
    }
    while(array[upper] > pivot){
      upper--;
    }

    //Swap upper and lower                                                          
    temp = array[lower];
    array[lower] = array[upper];
    array[upper] = temp;
  }

  //Repeat the past actions on the two partitions of the array recursively          
  quickSort(array, lower);
  quickSort(&array[lower+1], size-lower-1);
}

person Kalmar    schedule 03.12.2013    source แหล่งที่มา
comment
คุณพูดถูก การดูโค้ดของคุณอย่างรวดเร็ว อาจเกิดขึ้นได้ว่าทั้งค่าล่างไม่ได้เพิ่มขึ้นหรือค่าบนลดลง ซึ่งส่งผลให้เกิด inf วนซ้ำ (หาเคสแบบนี้ง่าย คือ เรียงเลขเหมือนกันหมด)   -  person gregory561    schedule 03.12.2013
comment
จะเกิดอะไรขึ้นเมื่อค่า Pivot มีหลายอินสแตนซ์? while ลูปในสุดทั้งสองลูปจะไม่ทำให้ lower และ upper มาบรรจบกัน อันหนึ่งควรเป็น < pivot และอีกอันคือ >= pivot   -  person Joe Z    schedule 03.12.2013
comment
ความคิดเห็นของคุณเกี่ยวกับความสัมพันธ์ระหว่างบน/ล่างกับจุดหมุนไม่เห็นด้วยกับโค้ด ดังนั้นหนึ่งในนั้นอาจมีข้อผิดพลาด   -  person molbdnilo    schedule 03.12.2013
comment
@JoeZ ฉันลองแล้ว แต่สุดท้ายกลับพบว่ามีข้อผิดพลาดในการแบ่งส่วน   -  person Kalmar    schedule 03.12.2013
comment
คุณอาจต้องทดสอบ upper ›= lower ใน while loop นั้นด้วย   -  person Joe Z    schedule 03.12.2013
comment
อาร์เรย์ที่เล็กที่สุดที่คุณพบว่าพบจุดบกพร่องนี้คืออะไร เกิดอะไรขึ้นเมื่อคุณก้าวผ่านการเรียงลำดับอาร์เรย์นี้ในดีบักเกอร์ ควร เกิดอะไรขึ้น?   -  person Useless    schedule 03.12.2013


คำตอบ (1)


แก้ไข: เพิ่มรหัส

จาก Wikipedia โค้ดหลอกสำหรับการจัดเรียงด่วนแบบแทนที่จะเป็นดังนี้:
(ไม่ได้บอกว่าควรเชื่อถือได้อย่างสุ่มสี่สุ่มห้า)

function quicksort(array)
    if length(array) > 1
        pivot := select any element of array
        left := first index of array
        right := last index of array
        while left ≤ right
            while array[left] < pivot
                left := left + 1
            while array[right] > pivot
                right := right - 1
            if left ≤ right
                swap array[left] with array[right]
                left := left + 1
                right := right - 1
        quicksort(array from first index to right)
        quicksort(array from left to last index)

คุณจะเห็นว่ามันค่อนข้างคล้ายกับอัลกอริธึมของคุณ โดยมีการแก้ไขเล็กน้อย

while(lower <= upper){

นอกจากนี้คุณต้องสลับเฉพาะเมื่อ lower <= upper แล้วอัปเดตดัชนี

และรหัสของคุณแตกต่างในการเรียกซ้ำ:

quicksort(array from first index to right) {array[0] to array[upper]}
quicksort(array from left to last index) {array[lower] to array[size-1]}

เนื่องจากตอนนี้ออกจากลูป while แล้ว ส่วนบนจะน้อยกว่าส่วนล่าง

รหัสการทำงานแบบเต็ม:

#include <iostream>
#include <cstdlib>
using namespace std;

void quickSort(int array[], int size){
  if(size < 2) return;

  int pivot, lower, upper, temp;

  //Set the indeces for the first and last elements                                 
  lower = 0;
  upper = size - 1;

  //Select pivot element randomly                                                   
  pivot = array[rand() % (size)];                                                                                                     

  while(lower <= upper){
    //Lower must be a number < than pivot and upper a number >= pivot               
    while(array[lower] < pivot){
      lower++;
    }
    while(array[upper] > pivot){
      upper--;
    }

    //Swap upper and lower                                                          
    if ( lower <= upper ) {
        temp = array[lower];
        array[lower] = array[upper];
        array[upper] = temp;
        lower++;
        upper--;
    }
  }

  //Repeat the past actions on the two partitions of the array recursively          
  quickSort(array, upper+1);
  quickSort(&array[lower], size-lower);
}

int main() {
    // your code goes here
    int myArray[] = { 10, 9, 8, 7, 7, 7, 7, 3, 2, 1};
    quickSort( myArray, 10 );
    for ( int i = 0; i < 10; i++ )
        cout << myArray[i] << " ";
    return 0;
}

เอาท์พุท:

1 2 3 7 7 7 7 8 9 10
person Abhishek Bansal    schedule 03.12.2013