2013-04-22 2 views
1

먼저, 숙제라고 말하고 싶습니다.중복이있는 int의 이진 파일을 사용하는 퀵 소트. 재귀에 문제가 있음

종종 우리는 과제를 끝내고 질문을 게시 할 것이며 과제를 계속하기 위해 계속 노력하고 싶지만이 경우에는 난처하게됩니다!

우리는 file.seek, file.read 및 file.write 명령 만 사용하여 이진 파일을 사용하여 퀵 포트를 구현해야합니다. 이것은 정수의 2 진 파일입니다.

피벗의 "하위 트리"에서 함수를 호출하는 재귀 부분입니다. 저는이 웹 사이트에 올린 알고리즘을 따르고 있습니다 : http://xoax.net/comp_sci/crs/algorithms/lessons/Lesson4/ 그리고 이진 파일 구현을위한 의사 코드로 코드 예제를 사용해 왔습니다.

여기 내 코드입니다 :

//Algorithm and code example used: 
void manage(fstream & file , int lindex , int fSize){ 


    //Chunks of 1 or 0 do not need sorting 
    if(fSize <= 1) 
     return; 

    //Choose point in file as "pivot." Pivot is a value. 
    //pp is the index of "pivot" 
    int pp = (rand() % fSize) + lindex; 
    file.seekp(pp * sizeof(int) , file.beg); 
    int pivot; 
    file.read((char*)&pivot , sizeof(int)); 

    //Choose "indices" to be swapped. These will be used in seekp 
    int leftIndex = lindex; 
    int rightIndex = fSize - 1; 

    //Swap val , swap val, temp storage, swap index 1 , swap index 2 
    int leftSwap , rightSwap , temp , tempI1 , tempI2 = 0; 

    //Dummy indecies to help with tracking partitions. 
    int dumL = leftIndex; 
    int dumR = rightIndex; 

    while(dumL < dumR){ 

     //Move to left index from the file beginning. 
     file.seekp(dumL * sizeof(int) , file.beg); 

     do{ 

      tempI1 = file.tellp()/sizeof(int); 
      dumL = tempI1; 
      file.read((char*)&temp , sizeof(int)); 
     } 

     while(temp < pivot); 

     leftSwap = temp; 

     //Move to right index. 
     file.seekp(dumR * sizeof(int) , file.beg); 
     int n = 1; 

     do{ 

      tempI2 = file.tellp()/sizeof(int); 
      dumR = tempI2; 
      file.read((char*)&temp , sizeof(int)); 
      file.seekp((rightIndex - n) * sizeof(int) , file.beg); 
      n++; 
     }   

     while(temp > pivot); 

     rightSwap = temp; 

     //Swap values 
     int hold = 0; 

     if(leftSwap == rightSwap && rightSwap == pivot) 
      break; 

     file.seekp(tempI1 * sizeof(int) , file.beg); 
     file.read((char*)&hold , sizeof(int)); 

     file.seekp(tempI1 * sizeof(int) , file.beg); 
     file.write((char*)&rightSwap , sizeof(int)); 

     file.seekp(tempI2 * sizeof(int) , file.beg); 
     file.write((char*)&leftSwap , sizeof(int)); 
    } 

    cout << "pp: " << pp << endl; 
    cout << "dumL: " << dumL << endl; 
    cout << "dumR: " << dumR << endl << endl; 

    //cout << "Lmanage: \n\t Lindex: 0\n\tSize: " << dumL << endl; 
    manage(file , 0 , dumL); 
    //cout << "Rmanage: \n\t Lindex: " << dumL + 1 << "\n\tSize: " << fSize - dumL - 1 << endl; 
    manage(file , dumL + 1 , fSize - (dumL - leftIndex) - 1); 
} 


void quicksort(fstream & file , int iSize){ 

    srand((unsigned int) time(0)); 
    manage(file , 0 , iSize); 
} 


int main(int argc, char* argv[]){ 

    if(argc != 2){ 

     cout << "Invalid number of arguments.\n"; 
     return -1; 
    } 

    fstream file; 
    int x = 0; 

    file.open(argv[1] , ios::binary | ios::out | ios::in); 

    //Calculate number of ints in file. 
    file.seekg(0 , file.end); 
    int size = file.tellg()/sizeof(int); 

    cout << "size: " << size << endl; 

    quicksort(file , size); 

    return 0; 
} 

"인수"가능한 중복 100 개 정수를 포함하는 바이너리 파일입니다. 문제는 첫 번째 1/4를 정렬하는 것으로 보이지만 색인 생성이 섞여서 "크기"인수가 부정적이된다는 것입니다.


편집 : 내 메인이 추가되었으며 설명이 변경되어 업데이트되었습니다.

+3

는 우선, 각 재귀 층으로 RNG 시드 중지합니다. 'srand()'는 프로그램 시작에 있어야합니다; 아무데도. 둘째, 빠른 정렬 구현에서 자주 발생하는 실수는 하위 시퀀스로 재귀 할 때 배치 된 피벗 슬롯을 건너 뛰지 않는 것입니다. 똑같은 실수를 저 지르지 않도록 코드를주의 깊게 살펴보십시오. 피벗은 되풀이되는 서브 시퀀스 중 하나 *에 포함되어서는 안됩니다. – WhozCraig

+0

또한, 파일 이름을'manage()'에 넘겨서는 안됩니다. 열린 fstream 참조를 전달한다. 해당 파일 핸들을 모두 열 필요는 없으며 공유에 문제가있을 것입니다. – WhozCraig

+0

나는 그것을 생각하고 처음에는했지만, 나는 내가 이해하지 못했던 커다란 오류를 얻었습니다. 나는 열린 파일을 인수로 전달할 수 없다고 생각했다. – Joshua

답변

1

적절한 qsort 알고리즘이 대중적인 선택이 아닐 수도 있지만,이 특정 인스턴스를 훨씬 이해하기 쉽게 만듭니다.

quicksort의 특성과 작동 방식을 보여주기 위해 재귀 들여 쓰기 '인쇄'메커니즘을 포함 시켰습니다. 샘플 실행 결과가 아래에 나타납니다. 나는 그것이 당신을 돕기를 바랍니다.

샘플 출력

0,100 
0,66 
    2,66 
    2,23 
    2,20 
    2,5 
    6,20 
     6,15 
     6,11 
     7,11 
     9,11 
     12,15 
     12,14 
     16,20 
     17,20 
     17,19 
    21,23 
    24,66 
    24,62 
    24,44 
     24,29 
     24,26 
     27,29 
     30,44 
     30,42 
     30,32 
     33,42 
     33,39 
      33,37 
      33,35 
     40,42 
    45,62 
     45,60 
     46,60 
     46,52 
     46,48 
     49,52 
      50,52 
     53,60 
     53,59 
      53,57 
      55,57 
    63,66 
67,100 
    67,72 
    67,69 
    70,72 
    73,100 
    73,94 
    73,85 
    73,80 
     73,75 
     76,80 
     76,78 
    81,85 
     81,84 
     82,84 
    86,94 
    86,89 
    90,94 
     90,92 
    95,100 
    95,99 
    97,99 

Sorted 
3 
8 
23 
27 
40 
54 
68 
78 
90 
97 
118 
120 
127 
130 
139 
149 
153 
155 
158 
168 
201 
210 
221 
235 
240 
241 
247 
260 
271 
274 
285 
292 
311 
317 
325 
327 
330 
332 
334 
362 
371 
410 
415 
427 
444 
478 
481 
487 
492 
499 
499 
513 
540 
542 
543 
543 
556 
567 
575 
578 
621 
624 
634 
634 
635 
661 
676 
676 
690 
693 
694 
706 
739 
777 
780 
793 
793 
798 
822 
834 
835 
836 
836 
850 
865 
871 
883 
884 
900 
903 
907 
917 
924 
924 
935 
943 
945 
946 
983 
996 
+0

와우 - 내가 찾던 것 이상이었다. 무리 감사. 다행스럽게도 내가 잘못하고있는 것을 알아낼 수 있기를 바랍니다. – Joshua

+0

@ Joshua 그것의 단지 다른 하위 알고리즘의 quicksort, double-ended 방식은 하나의 속성을 사지 않습니다. 필요에 따라 한 번에 하나씩 재배치하는 것이 아니라 반대 순서로 알려져있는 두 가지 요소를 서로 바꿉니다. 궁극적으로, O (nlogn)는 여전히 같고, 잠재적으로 * 덜 움직임입니다. 제가 말했듯이, 저는이 알고리즘을 선호합니다. 왜냐하면 특히 사람들에게 quicksort에 대해 가르 칠 때 이해하기가 훨씬 쉽기 때문입니다. 바라건대 당신도 동의합니다. – WhozCraig

관련 문제