加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

移位算法:面試和做項目必會

04/22 14:16
1481
閱讀需 11 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

最近在項目里需要對采樣數(shù)據(jù)做移位操作,研究了下幾個移位操作算法,今天通過本文分享給大家。我們知道位運算中有循環(huán)左移和右移運算,但是,對于數(shù)組,鏈表,Vecter容器等數(shù)據(jù)結(jié)構(gòu),就需要自己實現(xiàn)移位算法了,本文以數(shù)組作為例子,和大家一起學(xué)習(xí)幾種移位算法的實現(xiàn)。希望給大家在平時項目中能起到拋磚引玉的作用。

我們先設(shè)有一個數(shù)組data,數(shù)組data的大小為5,其值分別為{0,1,2,3,4},需要分別對數(shù)組data循環(huán)右移3個元素和循環(huán)向左移動3個元素。

第一種方法

首先,我們來看第一種方法,對于循環(huán)右移3個元素,我們可以分解成:先對每個元素都向右移動一個元素,其中最后一個元素需要放到數(shù)組的開頭位置,會得到一個新的數(shù)組,然后,用新的數(shù)組再做同樣的操作,如此循環(huán)3次,即可實現(xiàn)循環(huán)右移3個元素。

同樣的對于循環(huán)左移3個元素,也可這樣分解,只不過需要將每個元素需要先向左移動,其中開頭的元素就要放到末尾,得到的新數(shù)組。然后,再做同樣的操作3次。

下面是C++代碼實現(xiàn),函數(shù)中參數(shù)data是需要循環(huán)操作的數(shù)組,參數(shù)size是數(shù)據(jù)的大小,參數(shù)moveStep是移動元素的個數(shù),大于0表示向右移,小于0表示向左移。

void cycleShift1(int data[], int size, int moveStep){

auto rightMoveOnce = [&](int data[], int size)
{
int temp = data[size-1];
for(int i=size-1; i>0; i--)
{
data[i]=data[i-1];
}
data[0] = temp;
};

auto leftMoveOnce = [&](int data[], int size)
{
int temp = data[0];
for(int i=1; i<size; i++)
{
data[i-1]=data[i];
}
data[size-1] = temp;
};

moveStep %= size;
if(moveStep>0)
{
while(moveStep--)
{
rightMoveOnce(data, size);
}
}
else
{
while(moveStep++)
{
leftMoveOnce(data, size);
}
}
}

第二種方法

上面的第一種方法是最直觀的的一種方法,不過,它的時間復(fù)雜度相對高一些。我們可以通過使用空間換取時間的方法對其進(jìn)行優(yōu)化。

這種方法需要創(chuàng)建一個新的數(shù)組作為臨時輔助,以右移為例:

第一步,需要將結(jié)尾的三個數(shù)據(jù){2,3,4}存放到這個新的輔助數(shù)組中。

第二步,將開頭的兩個數(shù)據(jù){0,1}向右移動3個元素位置。

第三步,將輔助數(shù)組的數(shù)據(jù){2,3,4}放到開頭。

經(jīng)過上面三步之后,即可得到最終的結(jié)果。

類似的,對于循環(huán)左移,就需要將開頭的三個數(shù)據(jù){0,1,2}存放到輔助數(shù)組中,結(jié)尾的兩個數(shù)據(jù){3,4},向左移動3個元素位置。最后,再將輔助數(shù)組中的3個數(shù)據(jù)放到結(jié)尾。

下面是代碼實現(xiàn):

void cycleShift2(int data[], int size, int moveStep)
{
moveStep %= size;
if(moveStep>0)
{
int temp[moveStep] = {0};
for(int i = 0; i < moveStep; i++)
{
temp[i] = data[size - moveStep + i];
}

for(int i = 0; i < size - moveStep; i++)
{
data[size - i - 1] = data[size - moveStep - 1 - i];
}

for(int i = 0; i < moveStep; i++)
{
data[i] = temp[i];
}
}
else
{
moveStep *= -1;
int temp[moveStep] = {0};

for(int i = 0; i < moveStep; i++)
{
temp[i] = data[i];
}

for(int i = 0; i < size - moveStep; i++)
{
data[i] = data[moveStep + i];
}

for(int i=0; i < moveStep; i++)
{
data[size - moveStep + i] = temp[i];
}
}
}

第三種方法

我們還可以通過一個小技巧來實現(xiàn)循環(huán)移動的功能。

先看循環(huán)右移,首先,我們需要將數(shù)組分成兩部分,第一部分是{0,1},第二部分是{2,3,4}。

第一步,將{0,1}做個翻轉(zhuǎn),得到{1,0}

第二步,將{2,3,4}做個翻轉(zhuǎn),得到{4,3,2}

第三步,將{1,0,4,3,2}當(dāng)作一個整體,再次翻轉(zhuǎn),得到{2,3,4,0,1}。

三次翻轉(zhuǎn)之后,就可得到我們想要的結(jié)果。

同樣的對于循環(huán)左移,就需要將數(shù)組分成{0,1,2}和{3,4}兩部分。經(jīng)過三步的翻轉(zhuǎn),可以得到循環(huán)左移的結(jié)果。

下面是三次翻轉(zhuǎn)的代碼實現(xiàn):

void cycleShift3(int data[], int size, int moveStep)
{

auto reverse = [&](int data[], int startIndex, int endIndex)
{
for (; startIndex < endIndex; startIndex++, endIndex--)
{
double temp = data[endIndex];
data[endIndex] = data[startIndex];
data[startIndex] = temp;
}
};

moveStep %= size;

if(moveStep > 0) //Right shift
{
reverse(data, 0, size - moveStep - 1);
reverse(data, size - moveStep, size - 1);
}
else //Left shift
{
reverse(data, 0, 0 - moveStep - 1);
reverse(data, 0 - moveStep, size - 1);
}

reverse(data, 0, size - 1);
}

最后

上面和大家一起學(xué)習(xí)了三種移位算法的實現(xiàn),最后我們寫個小程序驗證一下三種算法的結(jié)果。

void printData(int data[], int size)
{
for(int i=0; i < size; i++)
{
std::cout << data[i] << " ";
}
std::cout << std::endl;
}

int main()
{

int data1_1[] = {0,1,2,3,4};
int data1_2[] = {0,1,2,3,4};
int data2_1[] = {0,1,2,3,4};
int data2_2[] = {0,1,2,3,4};
int data3_1[] = {0,1,2,3,4};
int data3_2[] = {0,1,2,3,4};
int size = 5;
int moveStep = 3;

std::cout << "-------------" << std::endl;
cycleShift1(data1_1, size, moveStep);
cycleShift1(data1_2, size, -1*moveStep);
printData(data1_1,size);
printData(data1_2,size);

std::cout << "-------------" << std::endl;
cycleShift2(data2_1, size, moveStep);
cycleShift2(data2_2, size, -1*moveStep);
printData(data2_1, size);
printData(data2_2, size);

std::cout << "-------------" << std::endl;
cycleShift3(data3_1, size, moveStep);
cycleShift3(data3_2, size, -1*moveStep);
printData(data3_1, size);
printData(data3_2, size);

}

感謝大家的閱讀,以上就是移位算法的全部內(nèi)容,希望大家從中能有所收獲,看完可以收藏以便查看,也記得轉(zhuǎn)發(fā)、點贊和點亮再看哈!感謝支持!

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險等級 參考價格 更多信息
USB3320C-EZK 1 SMSC Interface Circuit, 5 X 5 MM, 0.90 MM HEIGHT, ROHS COMPLIANT, QFN-32
$2.09 查看
KSZ9031RNXIA 1 Microchip Technology Inc DATACOM, ETHERNET TRANSCEIVER

ECAD模型

下載ECAD模型
$8.49 查看
NCV7344D10R2G 1 onsemi CAN FD Transceiver, High Speed, Low Power with NC, long filter time, 3000-REEL
$0.82 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜