rotate旋转分析(编程珠玑第二章)

来源:互联网 发布:淘宝订单p图教程 编辑:程序博客网 时间:2024/06/07 07:43

方法1:编程珠玑课后答案

代码解释:

不断得使得轴左右两边,元素数量少的一边的元素都处于正确的位置。知道左右两边处于非正确位置的元素个数相等时,直接交换,最坏的情况是左右两边只剩下一个元素,此时交换后即可得到rotate后的向量。

#include<iostream>

#include<vector>

using namespace std;

 

void swap(int begin,int mid,intn,vector<int> &num)

{

         for(int i=0;i<n;i++)

                  swap(num[begin+i],num[mid+i]);

}

 

void rotate(intm,vector<int> &num)

{

         if(m==0|| m==num.size())

                  return;

         inti=m;

         intj=num.size()-m;

         while(i!=j)

         {

                  if(i>j)

                  {

                          swap(m-i,m,j,num);

                          i-=j;

                  }

                  else

                  {

                          swap(m-i,m+j-i,i,num);

                          j-=i;

                  }

         }

         swap(m-i,m,i,num);

}

 

int main()

{

         intArr[]={1,2,3,4,5,6,7,8,9};

         vector<int>num(Arr,Arr+9);

         rotate(4,num);

 

         for(int i=0;i<num.size();i++)

                  cout<<num[i]<<"       ";

         cout<<endl;

 

 

         system("pause");

         return0;

}

方法2:用三次旋转来解决:

#include<iostream>

#include<vector>

using namespace std;

 

void rotate(intm,vector<int> &num)

{

         reverse(num.begin(),num.begin()+m);

         reverse(num.begin()+m,num.end());

         reverse(num.begin(),num.end());

}

 

int main()

{

         intArr[]={1,2,3,4,5,6,7,8,9};

         vector<int>num(Arr,Arr+9);

         rotate(0,num);

 

         for(int i=0;i<num.size();i++)

                  cout<<num[i]<<"       ";

         cout<<endl;

 

         system("pause");

         return0;

}

方法3:

解释:中间部分由3个参数的rotate函数是C++STL中的标准算法,与第二中算法大同小异。每进行一轮以后前面的几个元素已经就位,此时,如果first==mid则把mid后移,mid=next,此时只需要以新的mid为轴,旋转从first到最后即可。如果next已经到最后但是first没有到mid,则此时把next赋值为mid,继续进行以mid为轴的旋转。画图即可以看出,每次旋转的轴的变化情况。

#include<iostream>

#include<vector>

using namespace std;

 

void rotate(intm,vector<int> &num)

{

         intnext=m,first=0;

         while(first!=next)

         {

                  swap(num[first],num[next]);

                  first++;

                  next++;

                  if(next==num.size())

                          next=m;

                  elseif(first==m)

                          m=next;

         }

}

 

template <classForwardIterator>

  void rotate1(ForwardIterator first, ForwardIterator middle,

               ForwardIterator last)

{

  ForwardIterator next = middle;

  while(first!=next)//while (first!=num.size())这两种判定是一样的

  {                                      //但是用next判断效率更高,例如1,2,3,4,5,6,7,8,9,10,11,12,以第4个元素为轴,

                                            //则只需要旋转两次即可。如果用num.size()还需要做无用的交换

                                            //即此时first==next不用交换已经达到了rotate的目的。

    swap (*first++,*next++);

    if(next==last) next=middle;

    else if (first==middle) middle=next;

  }

}

 

int main()

{

         intArr[]={1,2,3,4,5,6,7,8,9,10,11,12};

         vector<int>num(Arr,Arr+12);

         rotate(8,num);

//  rotate1(num.begin(),num.begin()+4,num.end());

 

         for(int i=0;i<num.size();i++)

                  cout<<num[i]<<"       ";

         cout<<endl;

 

         system("pause");

         return0;

}

       在编程珠玑第二版P200第4题中图,如下图所示。


可见块交换所用的时间最短,这也是为什么STL用这种技术来进行旋转的原因。而不是用更容易理解的3次翻转。
0 0