CodeGuru Forums -
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic Newsletters VB Forums Developer.com


Newest CodeGuru.com Articles:

  • Faltering Windows support
  • Internet Explorer 8 Click Clever Click Safe
  • Release Candidate 2 for ASP.NET MVC 2
  • Learn How to Create Dual Mode Windows Services

  • Search CodeGuru:
     



    Go Back   CodeGuru Forums > Visual C++ & C++ Programming > C++ (Non Visual C++ Issues)
    FAQ Members List Calendar Search Today's Posts Mark Forums Read

    C++ (Non Visual C++ Issues) Ask or answer C and C++ questions not related to Visual C++. This includes Console programming, Linux programming, or general ANSI C++.

    Reply
     
    Thread Tools Search this Thread Rate Thread Display Modes
      #1    
    Old August 7th, 2009, 04:25 AM
    monarch_dodra monarch_dodra is online now
    Member
     
    Join Date: Jun 2009
    Posts: 389
    monarch_dodra will become famous soon enough (80+)
    combsort implementation. review.

    Hi,

    i was over at wikipedia reading about combsort (http://en.wikipedia.org/wiki/Comb_sort), I I fell on this c++ implementation.

    Code:
    template<class t> inline void combsort(t*a, int n)
    {
      int g=n,s=2;
      t*j,*i,z;
      while(s>1)for(i=a-1,s=g=(g/=1.3)>8&g<11?11:g?:1;++i<a+n-g;)z=*i,z>*(j=i+g)?s++,*i=*j,*j=z:7;
    }
    While I am sure writing this kind of code is fun, I am pretty sure reading about it won't help anyone. Also, I am pretty sure this function shouldn't be inline.

    I would like to re-write this pseudo algorithm:

    Code:
    function combsort11(array input)
        gap := input.size //initialize gap size
        
        loop until gap <= 1 and swaps = 0
            //update the gap value for a next comb
            if gap > 1
                gap := gap / 1.3
                if gap = 10 or gap = 9
                    gap := 11
                end if
            end if
            
            i := 0
            swaps := 0 //see bubblesort for an explanation
            
            //a single "comb" over the input list
            loop until i + gap >= input.size //see shellsort for similar idea
                if input[i] > input[i+gap]
                    swap(input[i], input[i+gap])
                    swaps := 1 // Flag a swap has occurred, so the list is not guaranteed sorted
                end if
                i := i + 1
            end loop
           
        end loop
    end function
    And I wrote this. I wanted the algorithm to be stl-style, easy to understand, and scalable. Could you guys look at it and tell me what you think? if somethings need change before I submit it?

    Code:
    template<class ForwardIterator>
    void combsort ( ForwardIterator first, ForwardIterator last )
    {
        static const double shrink_factor = 1.247330950103979;
        typename ForwardIterator::difference_type gap = std::distance(first, last);
        bool swaps = true;
    
        while ( (gap > 1) || (swaps == true) )
        {
            if (gap > 1)
            {
                gap = static_cast<typename ForwardIterator::difference_type>(
                    gap/shrink_factor
                );
                if ( (gap == 10) || (gap == 9) ) {gap = 11;}
            }
            swaps = false;
            ForwardIterator itLeft(first);
            ForwardIterator itRight(first); std::advance(itRight, gap);
            
            for ( ; itRight!=last; ++itLeft, ++itRight )
            {
                if ( (*itRight) < (*itLeft) )
                {
                    std::iter_swap(itLeft, itRight);
                    swaps = true;
                }
            }
        }
    }
    Reply With Quote
      #2    
    Old August 7th, 2009, 08:10 AM
    ltcmelo ltcmelo is offline
    Member
     
    Join Date: Jan 2006
    Location: Belo Horizonte, Brazil
    Posts: 387
    ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+) ltcmelo is a jewel in the rough (200+)
    Re: combsort implementation. review.

    Hello again.

    One problem I could note right way is that you assume a typedef for the iterator type. Remember from our recente discussion?

    Well, that's the whole point of std::iterator_traits. Some iterators classes do provide typedefs like difference_type. Others don't and need to specialize std::iterator_traits. A good example is a pointer. Pointers are built-ins and can't have a typedef inside. So there's an specialization of std::iterator_traits for pointers. (Try to compile your code passing a pointer to the function and you'll see the error.)

    The rule is that whenever you need to mention difference_type (or its related typedefs) you should use std::iterator_traits.

    Code:
    typename std::iterator_traits<ForwardIterator>::difference_type gap = std::distance(first, last);
    You also assume some requirements on the value_type of the iterator (the type that the iterator points to). For instance, you expect that they support operator <. If you don't want to depend on that you should use a function object as an additional template parameter. If you do, it would be good just to make it clear on the documentation.

    This is a first impression...
    __________________
    C++ Programming:
    - IDEs: Qt Creator, Visual C++ Express, Eclipse CDT, and CodeBlocks.
    - Docs: cplusplus, cppreference, and SGI.
    - FAQs: Stroustrup and Cline.

    http://sites.google.com/site/ltcmelo.

    If the post is useful or interesting, would you mind rating it? (There's a "reputation" button on the top right corner of the post box.)
    Reply With Quote
      #3    
    Old August 7th, 2009, 09:11 AM
    monarch_dodra monarch_dodra is online now
    Member
     
    Join Date: Jun 2009
    Posts: 389
    monarch_dodra will become famous soon enough (80+)
    Re: combsort implementation. review.

    Quote:
    Originally Posted by ltcmelo View Post
    Hello again.

    One problem I could note right way is that you assume a typedef for the iterator type. Remember from our recente discussion?

    Well, that's the whole point of std::iterator_traits. Some iterators classes do provide typedefs like difference_type. Others don't and need to specialize std::iterator_traits. A good example is a pointer. Pointers are built-ins and can't have a typedef inside. So there's an specialization of std::iterator_traits for pointers. (Try to compile your code passing a pointer to the function and you'll see the error.)

    The rule is that whenever you need to mention difference_type (or its related typedefs) you should use std::iterator_traits.

    Code:
    typename std::iterator_traits<ForwardIterator>::difference_type gap = std::distance(first, last);
    You also assume some requirements on the value_type of the iterator (the type that the iterator points to). For instance, you expect that they support operator <. If you don't want to depend on that you should use a function object as an additional template parameter. If you do, it would be good just to make it clear on the documentation.

    This is a first impression...
    Thankyou for the details about iterator_traits. I guess it is still not 100% clear. However, this finally clears up why you can't inherit from iterator traits

    As for the operator<, then yes, I do make this assumption, like all std algorithms do. There is always a "simple" algorithm, and another one that takes a functor:

    Code:
    template <class RandomAccessIterator>
      void sort ( RandomAccessIterator first, RandomAccessIterator last );
    
    template <class RandomAccessIterator, class Compare>
      void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );
    I could write the other implementation, but that would be overkill for wikipedia.

    Thankyou. here is the new code that works with pointers.

    Code:
    template<class ForwardIterator>
    void combsort ( ForwardIterator first, ForwardIterator last )
    {
        static const double shrink_factor = 1.247330950103979;
        typedef typename std::iterator_traits<ForwardIterator>::difference_type difference_type;
        difference_type gap = std::distance(first, last);
        bool swaps = true;
    
        while ( (gap > 1) || (swaps == true) )
        {
            if (gap > 1)
            {
                gap = static_cast<difference_type>(
                    gap/shrink_factor
                );
                if ( (gap == 10) || (gap == 9) ) {gap = 11;}
            }
            swaps = false;
            ForwardIterator itLeft(first);
            ForwardIterator itRight(first); std::advance(itRight, gap);
            
            for ( ; itRight!=last; ++itLeft, ++itRight )
            {
                if ( (*itRight) < (*itLeft) )
                {
                    std::iter_swap(itLeft, itRight);
                    swaps = true;
                }
            }
        }
    }
    Reply With Quote
    Reply

    Bookmarks
    Go Back   CodeGuru Forums > Visual C++ & C++ Programming > C++ (Non Visual C++ Issues)


    Thread Tools Search this Thread
    Search this Thread:

    Advanced Search
    Display Modes Rate This Thread
    Rate This Thread:

    Posting Rules
    You may not post new threads
    You may not post replies
    You may not post attachments
    You may not edit your posts

    BB code is On
    Smilies are On
    [IMG] code is On
    HTML code is Off
    Forum Jump


    All times are GMT -5. The time now is 08:57 AM.



    Acceptable Use Policy


    The Network for Technology Professionals

    Search:

    About Internet.com

    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers


    Powered by vBulletin® Version 3.7.3
    Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.