【例1】循環左移1位
輸入10個整數到數組a中,將數組各元素依次循環左移一個位置(如下圖1),輸出移動后的數組a。
圖1 數組元素循環左移1位
- 編程思路
先將a[0]保存起來(t=a[0]),再用一個循環將a[1]~a[9]依次前移一位,最后將預存起來的a[0]送至a[9]即可。
- 源程序及運行結果
#include <iostream>
using namespace std;
int main( )
{
int a[10],i,t ;
for (i=0;i<10;i++)
cin>>a[i];
t=a[0];
for(i=0;i<9;i++)
a[i]=a[i+1];
a[9]=t;
for (i=0;i<10;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
編譯並執行以上程序,得到如下所示的結果。
1 2 3 4 5 6 7 8 9 10
2 3 4 5 6 7 8 9 10 1
Press any key to continue
【例2】循環左移P位
設有n(n>1)個整數存放在一維數組R中。試設計一個在時間和空間兩方面盡可能高效的算法。將R中的序列循環左移P(0<P<n)個位置,即將R中的數據由(X0,X1,…Xn-1)變換為(Xp,Xp+1,…,Xn-1,X0,X1,…,Xp-1)。
- 編程思路1
上一個實例中,程序段:
t=a[0];
for(i=0;i<9;i++)
a[i]=a[i+1];
a[9]=t;
實現了循環左移1位。將這個程序段循環執行p次,即可完成循環左移p位的操作。
按這一思路所設計的算法的時間復雜度為O(p*n),空間復雜度為O(1)。
- 源程序1及運行結果
#include <iostream>
using namespace std;
int main()
{
int r[10]={1,2,3,4,5,6,7,8,9,10};
int i,p,t,times;
cout<<"請輸入需要左移的次數p (0<p<10):";
cin>>p;
cout<<"數組初始情況為:";
for (i = 0; i <10 ; i++)
cout<<r[i]<<" ";
cout<<endl;
for(times=1; times<=p; times++)
{
t=r[0];
for(i=0;i<9;i++)
r[i]=r[i+1];
r[9]=t;
}
cout<<"循環左移"<<p<<"位后,數組變換為:";
for (i = 0; i <10 ; i++)
cout<<r[i]<<" ";
cout<<endl;
return 0;
}
編譯並執行以上程序,得到如下所示的結果。
請輸入需要左移的次數p (0<p<10):4
數組初始情況為:1 2 3 4 5 6 7 8 9 10
循環左移4位后,數組變換為:5 6 7 8 9 10 1 2 3 4
Press any key to continue
- 編程思路2
定義一個可以放下p個整數的輔助數組temp,將數組R中的前p個整數依次存入輔助數組temp中,將R中后面的n-p個整數依次前移p個位置,將輔助數組中的數據依次取出,放入R中第n-p個整數開始的位置。
按這一思路所設計的算法的時間復雜度為O(n),空間復雜度為O(p)。
- 源程序2
#include <iostream>
using namespace std;
int main()
{
int r[10]={1,2,3,4,5,6,7,8,9,10};
int temp[10]; // 輔助數組,存放要移出的整數
int i,p;
cout<<"請輸入需要左移的次數p (0<p<10):";
cin>>p;
cout<<"數組初始情況為:";
for (i = 0; i <10 ; i++)
cout<<r[i]<<" ";
cout<<endl;
for(i=0;i<p;i++) // 將R中前p個數據存入輔助數組中
temp[i]=r[i];
for(i=0; i< 10-p;i++) // 將R中從第p個整數開始的整數前移p個位置
r[i]=r[p+i];
for(i=0; i<p; i++) // 將輔助數組中的p個數據放到R中第n-p個數據的后面
r[10-p+i]=temp[i];
cout<<"循環左移"<<p<<"位后,數組變換為:";
for (i = 0; i <10 ; i++)
cout<<r[i]<<" ";
cout<<endl;
return 0;
}
- 編程思路3
將數組R循環左移p位后,前p個數一定移動到后面,而后n-p移動到前面,因此可先將數組R逆置,然后再將R中前n-p個元素原地逆置,再將后p個元素原地逆置,如圖2所示。
圖2 用逆置的方法將數組R中的數據循環移位
為了程序編寫簡捷,可以將數組R中從begin開始到end結束(包括end)的元素進行逆置的操作寫成如下的函數:
void Reverse(int r[],int begin,int end)
{
int i,temp;
for(i=0;i<(end-begin+1)/2;i++)
{
temp=r[begin+i]; r[begin+i]=r[end-i]; r[end-i]=temp;
}
}
這樣,上述算法中三個Reverse函數的時間復雜度分別為O(n/2)、O((n-p)/2)和O(p/2),故所設計的算法的時間復雜度為O(n),空間復雜度為O(1)。
- 源程序3
#include <iostream>
using namespace std;
void Reverse(int r[],int begin,int end)
{
int i,temp;
for(i=0;i<(end-begin+1)/2;i++)
{
temp=r[begin+i]; r[begin+i]=r[end-i]; r[end-i]=temp;
}
}
int main()
{
int r[10]={1,2,3,4,5,6,7,8,9,10};
int i,p;
cout<<"請輸入需要左移的次數p (0<p<10):";
cin>>p;
cout<<"數組初始情況為:";
for (i = 0; i <10 ; i++)
cout<<r[i]<<" ";
cout<<endl;
Reverse(r,0,10-1); // 全部逆置
Reverse(r,0,10-p-1); // 前n-p個元素逆置
Reverse(r,10-p,10-1); // 后p個元素逆置
cout<<"循環左移"<<p<<"位后,數組變換為:";
for (i = 0; i <10 ; i++)
cout<<r[i]<<" ";
cout<<endl;
return 0;
}