Quick sort variants to achieve: the definition of a macro event raised late at night

I. Background  

  Bedtime suddenly wanted to write two lines of code to practice your hand, think of a variant of quick sort of realization, then wrote a quick sort, test results are very strange in theory, no problem situation, debug macros cause is found for a long time, as lessons recorded.

Second, the quick sort variants to achieve

  principle:

    |_| |_| |_________________________________________|

    L    R                     unSorted

              ---------------------------------------------------------------------------------------------------------------------

   1, taken Sentinel subscript Low, i.e., the first element; and R L set the initial state are empty, used to store the set value of L is less than the pivot, for storing a set of R value is greater than the pivot.

              pivot = vector<T>& vec[low] ;   mi = low;

                 ↓mi

              |——|

              |_| |_| |_________________________________________|

    L    R                     unSorted

   2, an initial set of traversal, if it is found greater than the current index of the element is added to a pivot iterator, without any operation, the effect is equivalent to moving elements of R.

                          idx

              |_| |__| |________________________________________|

    L    R                     unSorted

       3, if the found value is less than the current index of the element is required to pivot in the discharge current value set L in order to improve efficiency, so that the current element and the first element of the set R switching, and then adding an iterator; effect element corresponding to the new L increase, R elements after an overall shift.

                    me

                     ↓      idx

              |__| |__| |_______________________________________|

    L    R                     unSorted

  4, when the current sequence unSorted been traversed will be empty, L and R will contain all the smaller / larger than the pivot elements set.

                                                      me

                 ↓

              |___________________| |_________________________|

                    L                                           R

  5, the first element will eventually, i.e., pivot element and referred to exchange mi, mi is about the effect of this sentinel node has elected position, a trip sorting completed, the first half and the second half of the call after a recursive manner sorted (and the well known fast same row).

Third, the specific implementation, the following macro code implemented swap function is defined by, for compact logic, the parameters of the swap by the "+" operator. 

  1, the sorting logic                   

 1 #ifndef __ALGO_SORT_QUICK_SORT_IMPROVED_H__
 2 #define __ALGO_SORT_QUICK_SORT_IMPROVED_H__
 3 
 4 #include <vector>
 5 #include <iostream>
 6 using namespace std;
 7 
 8 #define swap(a, b)    ({\
 9     typeof(a) tmp = (a) ; \
10     (a) = (b); \
11     (b) = tmp; })
12 
13 template<typename Type>
14 static int partion(std::vector<Type>& elems, int low, int high)
15 {
16     Type pivot = elems[low];
17     int mi = low;
18     for (int i = low + 1; i <= high; i++)
19     {   
20         if (elems[i] < pivot)
21         {
22             //++mi;
23             swap(elems[++mi], elems[i]);
24         }
25     }   
26     swap(elems[mi], elems[low]);
27     return mi; 
28 }
29 
30 template<typename Type>
31 void quick_sort_improved(std::vector<Type>& elems, int low, int high)
32 {
33     if (low < high) 
34     {   
35         int mi = partion(elems, low, high);
36         quick_sort_improved(elems, low, mi - 1); 
37         quick_sort_improved(elems, mi + 1, high);
38     }   
39 }
40 
41 #endif

  2, the test program

1     vector<double> nums{18.1,16.12,32.21,12.22,13.1,53.21,221.5,354,123,42,22.11,33};
2     quick_sort_improved<double>(nums, 0, nums.size() - 1); 
3     for (int i = 0; i < nums.size(); i++ )
4     {   
5         cout << nums[i] << " ";
6     }   
7     cout << endl;

  3, test output

yg@yg-PC:~/workspace/Algo/src/sort/insertSort$ ./a.out 
6.52013e-319 6.52013e-319 6.52013e-319 12.22 12.22 16.12 33 0 0 0 42 42 

   4. Analysis: From the above results, the test results are not in accordance with the expected output, a mess.

Fourth, Remastered

  Plus a lot of debug information, that the problem lies in the use of incoming macro definition in the ++ operator, people familiar with the macro definition certainly had a similar problem; the current question is: macro definitions expression appears several times, ++ will be called several times, which is certainly not the desired result; slightly modified to know why.

template<typename Type>
static int partion(std::vector<Type>& elems, int low, int high)
{
    Type pivot = elems[low];
    int mi = low;
    for (int i = low + 1; i <= high; i++)
    {   
        if (elems[i] < pivot)
        {
            ++mi;
            swap(elems[mi], elems[i]);
        }
    }   
    swap(elems[mi], elems[low]);
    return mi; 
}

   Test output: correct, in line with expectations

yg@yg-PC:~/workspace/Algo/src/sort/insertSort$ ./a.out 
12.22 13.1 16.12 18.1 22.11 32.21 33 42 53.21 123 221.5 354

 

V. Summary

  Daily code macro definitions sometimes can not be avoided, as used above swap, even if the implementation has avoided a lot of low-level errors; but macro definition is still a lot to be desired, as shown above, the compiler even will not give a warning, it can also run normally run, but the pass is somehow the result of an error; through some struggles to find out the reason why, after the use of local macro definition must avoid this operation.

Guess you like

Origin www.cnblogs.com/zhangyi-studio/p/12117269.html