簡體   English   中英

在 C 中使用兩個指針左移/右移一個數組

[英]Left Shift/ Right Shift an array using two pointers in C

我正在嘗試對數組實現左移/右移

我能夠使用雙循環完成此操作。 我可以得到一些幫助來提高效率嗎?

這是使用 2 個循環的 LeftShift/RightShift 的工作代碼。

#include <iostream>
#include <stdlib.h>
#include <stdio.h> 

struct Array
{
    int A[10];
    int size;
    int length;
};

void Display(struct Array arr)
{
    printf("\nElements are : \n");
    for(int i = 0;i<arr.length;i++)
        printf("%d ", arr.A[i]);
}

// Left Shift-------------------------------------------------------------------------------------------------------
void LeftShift1(struct Array *arr, int n)    //n is the number of shifts
{
    int temp = arr->A[0];
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<arr->length-1; j++)
        {
            arr->A[j] = arr->A[j+1];
        }
        arr->A[arr->length-1] = 0;
    }
}

//Right Shift-------------------------------------------------------------------------------------------------------
void RightShift(struct Array *arr, int n)    //n is the number of shifts
{
    for(int i = 0; i<n; i++)
    {
        for(int j=arr->length-1; j>0; j--)
        {
            arr->A[j] = arr->A[j-1];
        }
        arr->A[0] = 0;
    }
    
}

int main()
{
    struct Array arr={{1,2,3,4,5},10,5};
    
    LeftShift1(&arr, 2);
    //RightShift(&arr, 1);

    Display(arr);

    return 0;
}    

我正在嘗試這樣的事情,它使用 2 個迭代器來解決這個問題!

這也有效!

void LeftShift2(struct Array *arr, int n)
{
    for(int k=0; k<n; k++)
    {
        int i,j;
        for(i=0, j=0; j<arr->length-1; i++, j++)
        {
            arr->A[j] = arr->A[j+1];
        }
        arr->A[arr->length-1] = 0;
    }
}

但這可以在沒有循環的情況下解決嗎? 還是用一個循環?

這可以提高效率嗎?

一些幫助提高效率?

移位:移位一次。 O(n*length)O(length)

輪換:一次轉變為臨時。 O(n*length)O(length)

首先確定尺寸數量。

void LeftShift_alt(struct Array *arr, int n) {
  if (n > arr->length) {
    n = arr->length;
  }
  memmove(arr, arr + n, sizeof *arr * (arr->length - n));
  memset(arr + n, 0, sizeof *arr * n);
}

void LeftRotate_alt(struct Array *arr, int n) {
  if (arr->length > 0) {
    n %= arr->length;
    if (n > 0) {
      int temp[n];
      memcpy(temp, arr, sizeof temp);
      memmove(arr, arr + n, sizeof *arr * (arr->length - n));
      memcpy(arr + n, temp, sizeof temp);
    }
  }
}

如果需要,將mem...()替換為指針代碼。

您可以在結構中提供所有常見的訪問運算符(<<、>>、[] 等),而不是實際移動數組的內容。 (假設您使用的是支持此功能的編譯器。否則,您將需要創建 C 風格的這些函數。)如果有人這樣做:

my_array <<= 5;
my_array >>= 2;

...您只需跟蹤數組已移動了多少。 在這種情況下,他們總共向左移動了 3 個位置。 當有人索引到數組中時,您將累積的偏移量添加到他們的索引(以數組的大小為模)以獲取他們正在尋找的條目的實際位置。 這使得移位 O(1) 而不是 O(n)。 如果您正在尋找一種有效的解決方案,那么這已經足夠了。

CODE REVIEW

在 C 中,可以通過使用單個循環來提高效率。 我們可以將元素移動n個位置,而不是一次移動一個位置!

像這樣的東西:

void LeftShift1(struct Array* arr, unsigned int n) {
    if (n > arr->length) {
        n = arr->length;
    }
    for (unsigned int i = 0; i < arr->length; i++) {
        if (i + n < arr->length)
            arr->A[i] = arr->A[i + n];
        else
            arr->A[i] = 0;
    }
}

在實際使用中,我們會考慮使用除普通int以外的元素類型進行數組移位。 事實上,它可能是一個像string一樣的復雜類型,我們不應該對字符串進行原始的memcpy

在我的代碼中,我將移出的元素設置為 0,這對於整數和相關類型是可以的,但它在字符串中不會類似地工作。

從 C++20 開始,有一個標准的std::shift_leftstd::shift_right可供使用。 還有std::rotate可用於旋轉元素。

int arr[] = {1,2,3,4,5};
using std::ranges::begin;
using std::ranges::end;
std::shift_left (begin(arr),end(arr),2);
Display(arr);

同樣在 C++ 中,我們應該使用像vector這樣的靈活容器來代替struct

此外,如果我們在兩端進行大量添加和刪除元素,那么有一個專門為稱為deque (“雙端隊列”)而設計的容器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM