Partition algorithm with two loops c++

╄→гoц情女王★ 提交于 2020-01-06 21:23:16

问题


I was given pseudo code for a partition algorithm but I'm not really sure how to implement it.

Below is the pseudo code and my implementation. Please let me know if this is correct/explain what it's doing. Right now I have a partial understanding of it but it is not correct.

Input: 0.963, 0.003, 0.0251, 0.353, 0.667, 0.838, 0.335, 0.915, 0.796, 0.833, 0.345, 0.871, 0.089, 0.888, 0.701, 0.735

Expected: 0.003 0.0251 0.089 0.335 0.345 0.353 0.667 0.701 0.735 0.796 0.833 0.838 0.871 0.888 0.915 0.963

Actual: 0.003000 0.025100 0.353000 0.667000 0.838000 0.335000 0.915000 0.796000 0.833000 0.345000 0.871000 0.089000 0.888000 0.7 01000 0.735000 0.963000

int partition_data( float xdata[], int ndata, float xmiddle ) {
  int left;
  int right;
  int j,i;
  float temp;

  for(i = 0; i < xmiddle; i ++){
    if(left == right){
      left += 1;
    }
    else{
      for( j = ndata - 1; j >= xmiddle; j--){
        if(left == right){
          right -= 1;
        }
        else{
          temp = xdata[j];
          xdata[j] = xdata[i];
          xdata[i] = temp;

          right -= 1;
          if(left == right){
            left += 1;
            break;
          }
        }
      }
    }
  }

}

回答1:


As others already said, both here and at Code Review, the pseudocode is quite non-standard, and hard to read (although it's not true it is mis-indented).

However, if you're not interested in improving it, but just want to implement it 'as is', here it is, word-by-word translated into C language:

int Partition(float X[], int ndata, float xmiddle)
{
    int left  = 0;
    int right = ndata - 1;
    while(1) {              // 'left' loop
        if(X[left] < xmiddle)
        {
            if(left == right)
                return left + 1;
            left ++;
        }
        else
            while(1) {     // 'right' loop
                if(X[right] >= xmiddle)
                {
                    if(left == right)
                        return left;
                    right --;
                }
                else
                {
                    float tmp = X[left];    // these three lines
                    X[left] = X[right];     // swap the two values
                    X[right] = tmp;         // X[left] and X[right]

                    right --;
                    if(left == right)
                        return left + 1;
                    left ++;
                    break;           // exit the 'right' loop
                }
            }     // end of 'right' loop
    }   // end of 'left' loop
} // end of Parition

The code is actually C, in C++ you might make it a function template with a type parameter instead of explicit float, so that the function may partition arrays of different types (as long as operators < and >= are defined). You might also use std::swap for efficient swapping data and dropping the explicit tmp variable.




回答2:


Maybe the assignment was to implement a full quicksort?

Quicksort with conventional pre-increment / pre-decrement Hoare partition scheme:

int Partition(float x[], int lo, int hi)
{
float xmiddle = x[(lo+hi)/2];
int left = lo - 1;
int right = hi + 1;
float tmp;
    while (1){
        while (x[++left]  < xmiddle);
        while (x[--right] > xmiddle);
        if(left >= right)
            break;
        tmp = x[left];
        x[left] = x[right];
        x[right] = tmp;
    }
    return right;
}

void QuickSort(float x[], int lo, int hi){
int pivot;
    if (lo < hi){
        pivot = Partition(x, lo, hi);
        QuickSort(x, lo, pivot);
        QuickSort(x, pivot+1, hi);
    }
}

One issue with quicksort is that a minor bug in the partition scheme may work for most data patterns and only fail for specific data patterns, making it difficult to determine if a quicksort is really bug free.

Quicksort using modified version from the psuedo code above. This works for the example data, but I'm not sure it's bug free. Partition should return an index that points to a value == xmiddle:

int Partition(float X[], int lo, int hi)
{
    int left  = lo;
    int right = hi;
    float xmiddle = X[(lo+hi)/2];
    float tmp;
    while(1) {
        while(X[left] < xmiddle){
            if(left == right)
                return left+1;
            left++;
        }
        while(X[right] >= xmiddle){
            if(left == right)
                return left;
            right--;
        }
        tmp      = X[left];
        X[left]  = X[right];
        X[right] = tmp;
        right --;
        if(left == right)
            return left + 1;
        left ++;
    }
}

void QuickSort(float x[], int lo, int hi){
int pivot;
    if (lo < hi){
        pivot = Partition(x, lo, hi);
        QuickSort(x, lo, pivot);
        QuickSort(x, pivot+1, hi);
    }
}



回答3:


Explanation of the algorithm

The routine re-arranges data so that items less than the supplied xmiddle value remain on the left side of the array (at smaller indices) and items greater than xmiddle are put to the right part (at bigger indices). The return value is a length of the left part.

Variables left and right scan the array from both ends to find items which should be swapped.

The 'left loop' (starting at line 4) increments the left index until it finds an item greater than or equal to xmiddle (line 5) or until it reaches the right position (line 6). As right is initially the last index of the array (and later it can only be decremented), the loop must eventually stop incrementing left.

If the left index meets right then all items below and at left are less than xmiddle, so left+1 is returned as a length of the left subarray. Note that if xmiddle is chosen bigger than all items of the array, the return value is equal to the array's length (ndata).

If left stops at an item greater than or equal to xmiddle, then the 'otherwise' branch at line 9 executes and the 'right loop' starts. Similar to the left loop it decrements right, stepping over all items greater than or equal to xmiddle until the right index meets left. If the two indices meet (line 11), then all items below them are less than, and all items above and at them are greater than or equal to xmiddle; then left is returned as the length of the left part.

On the other hand, if the right index finds an item less than xmiddle (i.e. not satisfying the condition at line 10), then it needs to be swapped with the item at index left, which is greater than or equal to xmiddle (it didn't satisfy the condition at line 5). Then the 'otherwise' branch at line 13 is executed.

The branch swaps the two values (line 14), so both left and right part become one item longer. To reflect that, the right index is decremented (line 15) and then compared to left. If they got equal (line 16), i.e. we swapped adjacent items, the partitioning is done, so left+1 is returned as a length of the left part. Otherwise left gets incremented (line 17) and we exit the 'right loop' (line 18) and proceed to the closing brace of the 'left loop' in line 20, which brings the execution back to line 4.

Then again left gets incremented (that is the left part grows) until it meets the right part or finds an item to be swapped. And so on...

The loops invariants are:

  • leftright
  • X[i] < xmiddle for 0 ≤ i < left
  • X[i] ≥ xmiddle for right < i < ndata

and the un-tested part of the array gets reduced (the difference right - left is decremented) at least by 1 in every iteration of a loop.



来源:https://stackoverflow.com/questions/34002448/partition-algorithm-with-two-loops-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!