亚洲一级免费看,特黄特色大片免费观看播放器,777毛片,久久久久国产一区二区三区四区,欧美三级一区二区,国产精品一区二区久久久久,人人澡人人草

C語言

C++實(shí)現(xiàn)一維向量旋轉(zhuǎn)算法

時(shí)間:2025-04-29 12:12:34 C語言 我要投稿
  • 相關(guān)推薦

C++實(shí)現(xiàn)一維向量旋轉(zhuǎn)算法

  C++實(shí)現(xiàn)一維向量旋轉(zhuǎn)的算法的怎么編程的呢?下面內(nèi)容由小編為大家介紹C++實(shí)現(xiàn)一維向量旋轉(zhuǎn)算法,供大家參考!

  在《編程珠璣》一書的第二章提到了n元一維向量旋轉(zhuǎn)算法(又稱數(shù)組循環(huán)移位算法)的五種思路,并且比較了它們在時(shí)間和空間性能上的區(qū)別和優(yōu)劣。本文將就這一算法做較為深入的分析。具體如下所示:

  一、問題描述

  將一個(gè)n元一維向量向左旋轉(zhuǎn)i個(gè)位置。例如,假設(shè)n=8,i=3,向量abcdefgh旋轉(zhuǎn)為向量defghabc。簡單的代碼使用一個(gè)n元的中間向量在n步內(nèi)可完成該工作。你能否僅使用幾十個(gè)額外字節(jié)的內(nèi)存空間,在正比于n的時(shí)間內(nèi)完成向量的旋轉(zhuǎn)?

  二、解決方案

  思路一:將向量x中的前i個(gè)元素復(fù)制到一個(gè)臨時(shí)數(shù)組中,接著將余下的n-i個(gè)元素左移i個(gè)位置,然后再將前i個(gè)元素從臨時(shí)數(shù)組中復(fù)制到x中余下的位置。

  性能:這種方法使用了i個(gè)額外的位置,如果i很大則產(chǎn)生了過大的存儲(chǔ)空間的消耗。

  C++代碼實(shí)現(xiàn)如下:

  /*************************************************************************

  > File Name: vector_rotate.cpp

  > Author: SongLee

  ************************************************************************/

  #include

  #include

  using namespace std;

  int main()

  {

  string s = "abcdefghijklmn";

  cout << "The origin is: " << s << endl;

  // 左移個(gè)數(shù)

  int i;

  cin >> i;

  if(i > s.size())

  {

  i = i%s.size();

  }

  // 將前i個(gè)元素臨時(shí)保存

  string tmp(s, 0, i);

  // 將剩余的左移i個(gè)位置

  for(int j=i; j

  {

  s[j-i] = s[j];

  }

  s = s.substr(0, s.size()-i) + tmp;

  cout << "The result is: "<< s << endl;

  return 0;

  }

  思路二:定義一個(gè)函數(shù)將x向左旋轉(zhuǎn)一個(gè)位置(其時(shí)間正比于n),然后調(diào)用該函數(shù)i次。

  性能:這種方法雖然空間復(fù)雜度為O(1),但產(chǎn)生了過多的運(yùn)行時(shí)間消耗。

  C++代碼實(shí)現(xiàn)如下:

  /*************************************************************************

  > File Name: vector_rotate_1.cpp

  > Author: SongLee

  ************************************************************************/

  #include

  #include

  using namespace std;

  void rotateOnce(string &s)

  {

  char tmp = s[0];

  int i;

  for(i=1; i

  {

  s[i-1] = s[i];

  }

  s[i-1] = tmp;

  }

  int main()

  {

  string s = "abcdefghijklmn";

  cout << "The origin is: " << s << endl;

  // 左移個(gè)數(shù)

  int i;

  cin >> i;

  if(i > s.size())

  {

  i = i%s.size();

  }

  // 調(diào)用函數(shù)i次

  while(i--)

  {

  rotateOnce(s);

  }

  cout << "The result is: "<< s << endl;

  return 0;

  }

  思路三:移動(dòng)x[0]到臨時(shí)變量t中,然后移動(dòng)x[i]到x[0]中,x[2i]到x[i],依次類推,直到我們又回到x[0]的位置提取元素,此時(shí)改為從臨時(shí)變量t中提取元素,然后結(jié)束該過程(當(dāng)下標(biāo)大于n時(shí)對n取;蛘邷p去n)。如果該過程沒有移動(dòng)全部的元素,就從x[1]開始再次進(jìn)行移動(dòng),總共移動(dòng)i和n的最大公約數(shù)次。

  性能:這種方法非常精巧,像書中所說的一樣堪稱巧妙的雜技表演?臻g復(fù)雜度為O(1),時(shí)間復(fù)雜度為線性時(shí)間,滿足問題的性能要求,但還不是最佳。

  C++代碼實(shí)現(xiàn)如下:

  /*************************************************************************

  > File Name: vector_rotate_2.cpp

  > Author: SongLee

  ************************************************************************/

  #include

  #include

  using namespace std;

  // 歐幾里德(輾轉(zhuǎn)相除)算法求最大公約數(shù)

  int gcd(int i, int j)

  {

  while(1)

  {

  if(i > j)

  {

  i = i%j;

  if(i == 0)

  {

  return j;

  }

  }

  if(j > i)

  {

  j = j%i;

  if(j == 0)

  {

  return i;

  }

  }

  }

  }

  int main()

  {

  string s = "abcdefghijklmn";

  cout << "The origin is: "<< s << endl;

  // 左移個(gè)數(shù)

  int i;

  cin >> i;

  if(i > s.size())

  {

  i = i%s.size();

  }

  // 移動(dòng)

  char tmp;

  int times = gcd(s.size(), i);

  for(int j=0; j

  {

  tmp = s[j];

  int pre = j; // 記錄上一次的位置

  while(1)

  {

  int t = pre+i;

  if(t >= s.size())

  t = t-s.size();

  if(t == j) // 直到tmp原來的位置j為止

  break;

  s[pre] = s[t];

  pre = t;

  }

  s[pre] = tmp;

  }

  cout << "The result is: "<< s << endl;

  return 0;

  }

  思路四:旋轉(zhuǎn)向量x實(shí)際上就是交換向量ab的兩段,得到向量ba,這里a代表x的前i個(gè)元素。假設(shè)a比b短。將b分割成bl和br,使br的長度和a的長度一樣。交換a和br,將ablbr轉(zhuǎn)換成brbla。因?yàn)樾蛄衋已在它的最終位置了,所以我們可以集中精力交換b的兩個(gè)部分了。由于這個(gè)新問題和原先的問題是一樣的,所以我們以遞歸的方式進(jìn)行解決。這種方法可以得到優(yōu)雅的程序,但是需要巧妙的代碼,并且要進(jìn)行一些思考才能看出它的效率足夠高。

  //實(shí)現(xiàn)代碼(略)

  思路五:(最佳)將這個(gè)問題看做是把數(shù)組ab轉(zhuǎn)換成ba,同時(shí)假定我們擁有一個(gè)函數(shù)可以將數(shù)組中特定部分的元素逆序。從ab開始,首先對a求逆,得到arb,然后對b求逆,得到arbr。最后整體求逆,得到(arbr)r,也就是ba。

  ?

  1

  2

  3

  reverse(0, i-1) /*cbadefgh*/

  reverse(i, n-1) /*cbahgfed*/

  reverse(0, n-1) /*defghabc*/

  性能:求逆序的方法在時(shí)間和空間上都很高效,而且代碼非常簡短,很難出錯(cuò)。

  C++代碼實(shí)現(xiàn)如下:

  /*************************************************************************

  > File Name: vector_rotate.cpp

  > Author: SongLee

  ************************************************************************/

  #include

  #include

  using namespace std;

  void reverse(string &s, int begin, int end)

  {

  while(begin < end)

  {

  char tmp = s[begin];

  s[begin] = s[end];

  s[end] = tmp;

  ++begin;

  --end;

  }

  }

  int main()

  {

  string s = "abcdefghijklmn";

  cout << "The origin is: "<< s << endl;

  int i;

  cin >> i;

  if(i > s.size())

  {

  i = i%s.size();

  }

  reverse(s, 0, i-1);

  reverse(s, i, s.size()-1);

  reverse(s, 0, s.size()-1);

  cout << "The result is: "<< s << endl;

  return 0;

  }

  三、擴(kuò)展延伸

  如何將向量abc旋轉(zhuǎn)變成cba?

  和前面的問題類似,此向量旋轉(zhuǎn)對應(yīng)著非相鄰內(nèi)存塊的交換模型。解法很相似,即利用恒等式:cba = (arbrcr)r


【C++實(shí)現(xiàn)一維向量旋轉(zhuǎn)算法】相關(guān)文章:

C++實(shí)現(xiàn)自頂向下的歸并排序算法03-24

C++實(shí)現(xiàn)自底向上的歸并排序算法03-14

堆排序算法及用C++實(shí)現(xiàn)基于最大堆的堆02-12

C++選擇排序算法實(shí)例02-25

權(quán)重隨機(jī)算法的java實(shí)現(xiàn)08-13

PHP實(shí)現(xiàn)抽獎(jiǎng)概率算法03-21

C++插入排序算法實(shí)例06-02

C++歸并排序算法實(shí)例02-09

C++冒泡排序算法實(shí)例詳解06-09