您的位置:首页 > 职场人生

读程序员编程艺术第一章---左旋字符串(二)

2014-03-16 20:05 483 查看
上一遍介绍了左旋字符串的第一种方法,暴力移位法。今天我们通过指针翻转法来实现左旋字符串。下面看一个例子。字符串“abcdefghijk”通过左移得到"defghijkabc"。我们可以通过两步来实现。首先定义两个指针p1,p2指向要交换的两个字符,如p1指向a,p2指向d,将p1与p2指向的字符进行交换,然后p1++,p2++。这样反复重复,知道p2指向末尾的字符。这样可以得到字符串defghijkcab。剩下的就是处理尾巴。此时我们可以知道p1指向c,p2指向b,将ab向左移动两个单位既可以得到的字符串。

下面是代码实现:

#include "stdafx.h"
#include"string"
#include"iostream"
using namespace std;

void rotate(string &str,int m)
{

//例如"abcdefghijk",其中n=11,m=3
//做简单的初始化工作
int n=str.length();
int p1=0;
int p2=m;
//p2指到最后,操作完之后变为defghijkcab
while(true)
{
swap(str[p1],str[p2]);
p1++;
if(p2<n-1)
{
p2++;
}
else
{
break;
}
}
//现在处理尾巴,需要移动的位数为r
int r=m-(n%m);
while(r--)
{
int i=p1;
char temp=str[i];
while(i<p2)
{
str[i]=str[i+1];
i++;
}
str[p2]=temp;
}

}

int main()
{
string str="abcdefghijk";
cout<<str<<endl;
rotate(str,str.length(),3);
cout<<str<<endl;
return 0;
}


还有一种方法也可以实现:

当字符串变为defghiabcjk的时候,p1指向a,p2指向j。将jk移到abc之前即可。代码编写如下:

#include "stdafx.h"
#include"string"
#include"iostream"
using namespace std;

void rotate(string &str,int m)
{

//例如"abcdefghijk",其中n=11,m=3
//做简单的初始化工作
int n=str.length();
int p1=0;
int p2=m;
//计算可以交换的次数k
int k=n-m-(n%m);
//操作之后为defghiabcjk
for(int i=1;i<=k;i++)
{
swap(str[p1],str[p2]);
p1++;
p2++;
}
//需要交换的位数r
int r=n-p2;
while(r--)
{
int i=p2;
while(i>p1)
{
swap(str[i],str[i-1]);
i--;
}
p1++;
p2++;
}
}

int main()
{
string str="abcdefghijk";
cout<<str<<endl;
rotate(str,3);
cout<<str<<endl;
return 0;
}


还有一种更为巧妙的方法就是通过递归翻转,逐步减小问题的规模。左右的回荡。如“abcdefghijk”首先进行左旋得到“defghiabcjk”,然后将尾部“abcjk”看做一个单独的问题进行右旋得到“ajkbc”。再将“ajk”看做一个更小的问题进行左旋。这样不断的左旋右旋,直到n%m=0时才停止,这样就解决了这个问题。代码编写如下:

#include "stdafx.h"
#include"string"
#include"iostream"
using namespace std;

//通过递归来实现左移字符串
//"abcdefghijk"通过简单的左移之后"defghiabcjk",
//现在可以考虑将"abcjk"中的jk右旋得到"ajkbc",
//现在相当于将"ajk"左旋得到"jka"结束。

void rotate(string &str,int n,int m,int head,int tail,bool flag)
{
//flag为true表示左旋,head表示起始字符位置,tail表示结束字符位置
if(head==tail)
return;
if(flag==true)
{
//初始化操作
int p1=head;
int p2=head+m;
//可以右移的位数
int k=n-m-(n%m);
for(int i=0;i<k;i++)
{
swap(str[p1],str[p2]);
p1++;
p2++;
}
//将剩下的部分做右旋操作,其中的长度为n-k,右旋位数为n%m,起始字符为现在的p1,结束位置为tail
rotate(str,n-k,n%m,p1,tail,false);
}
else
{
//初始化操作
int p1=tail;
int p2=tail-m;
int k=n-m-(n%m);
for(int i=0;i<k;i++)
{
swap(str[p1],str[p2]);
p1--;
p2--;
}
//将剩下的部分做左旋操作
rotate(str,n-k,n%m,head,p1,true);
}
}

int main()
{
string str="abcdefghijk";
cout<<str<<endl;
rotate(str,str.length(),3,0,str.length()-1,true);
cout<<str<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: