Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 就地连接阵列_C_Arrays_Algorithm_Buffer - Fatal编程技术网

C 就地连接阵列

C 就地连接阵列,c,arrays,algorithm,buffer,C,Arrays,Algorithm,Buffer,我在实现循环缓冲区时遇到了一个问题,该缓冲区必须偶尔对齐 假设我有两个数组,leftArr和rightArr。我想将右数组移动到byteArr,将左数组移动到byteArr+右数组的长度。leftArr和rightArr都大于byteArr,rightArr大于leftArr。(这与此不同,因为左数组不需要从byteArr开始)尽管左数组和右数组不重叠,但存储在byteArr的组合数组可能与存储在leftArr和rightArr的当前数组重叠。从byteArr到rightArr+rightarl

我在实现循环缓冲区时遇到了一个问题,该缓冲区必须偶尔对齐

假设我有两个数组,
leftArr
rightArr
。我想将右数组移动到
byteArr
,将左数组移动到
byteArr
+右数组的长度。
leftArr
rightArr
都大于
byteArr
rightArr
大于
leftArr
。(这与此不同,因为左数组不需要从
byteArr
开始)尽管左数组和右数组不重叠,但存储在
byteArr
的组合数组可能与存储在
leftArr
rightArr
的当前数组重叠。从
byteArr
rightArr+rightarlen
的所有内存都可以安全写入。一种可能的实施方式是:

void align(char* byteArr, char* leftArr, int leftArrLen, char* rightArr, int rightArrLen) {
  char *t = malloc(rightArrLen + leftArrLen);

  // form concatenated data
  memcpy(t, right, rightArrLen);
  memcpy(t + rightArrLen, left, leftArrLen);

  // now replace
  memcpy(byteArr, t, rightArrLen + leftArrLen);
  free(t);
}
然而,我必须以恒定的内存复杂性来完成这项工作

到目前为止,我得到的结果如下:

void align(char* byteArr, char* leftArr, int leftArrLen, char* rightArr, int rightArrLen)
{
    // first I check to see if some combination of memmove and memcpy will suffice, if not:
    unsigned int lStart = leftArr - byteArr;
    unsigned int lEnd = lStart + leftArrLen;
    unsigned int rStart = rightArr - byteArr;
    unsigned int rEnd = rStart + rightArrLen;
    unsigned int lShift = rEnd - rStart - lStart;
    unsigned int rShift = -rStart;
    char temp1;
    char temp2;
    unsigned int nextIndex;
    bool alreadyMoved;

    // move the right array
    for( unsigned int i = 0; i < rEnd - rStart; i++ )
    {
        alreadyMoved = false;

        for( unsigned int j = i; j < rEnd - rStart; j-= rShift )
        {
            if(    lStart <= j + rStart - lShift
                && j + rStart - lShift < lEnd
                && lStart <= (j + rStart) % lShift
                && (j + rStart) % lShift < lEnd
                && (j + rStart) % lShift < i )
            {
                alreadyMoved = true;
            }
        }

        if(alreadyMoved)
        {
            // byte has already been moved
            continue;
        }

        nextIndex = i - rShift;
        temp1 = byteArr[nextIndex];
        while( rStart <= nextIndex && nextIndex < rEnd )
        {
            nextIndex += rShift;
            temp2 = byteArr[nextIndex];
            byteArr[nextIndex] = temp1;
            temp1 = temp2;
            while( lStart <= nextIndex && nextIndex < lEnd )
            {
                nextIndex += lShift;
                temp2 = byteArr[nextIndex];
                byteArr[nextIndex] = temp1;
                temp1 = temp2;
            }
            if( nextIndex <= i - rShift )
            {
                // byte has already been moved
                break;
            }
        }
    }

    // move the left array
    for( unsigned int i = lStart; i < lShift && i < lEnd; i++ )
    {
        if( i >= rEnd - rStart )
        {
            nextIndex = i + lShift;
            temp1 = byteArr[nextIndex];
            byteArr[nextIndex] = byteArr[i];
            while( nextIndex < lEnd )
            {
                nextIndex += lShift;
                temp2 = byteArr[nextIndex];
                byteArr[nextIndex] = temp1;
                temp1 = temp2;
            }
        }
    }
}

想象一下将
按tearr
划分为多个区域(不一定按比例):

  • 现在有两种选择

    • 如果R2的长度与Left相同或更长,则将Left与R2的初始部分交换以生成(仍不按比例缩放):
  • R1'X2''左R2' |------|-----|-------|--|
    • 否则,将Left的初始部分与所有R2进行交换以生成(仍不缩放):
    R1'L2 X2'L1 |------|---|-------|----|
  • 现在认识到,在任何一种情况下,您都有一个与原始问题形式相同的严格较小的问题,其中新的
    byteArr
    是原始问题的尾部,紧跟在区域R1'之后。在第一种情况下,新的
    leftArr
    是(最终的)左侧区域,新的
    rightArr
    是区域R2'。在另一种情况下,新的
    leftArr
    是区域L2,而新的
    rightArr
    是区域L1。重置参数以反映此新问题,并返回到步骤(1)

  • 请注意,我说要返回到步骤1。当然,您可以递归地实现这个算法(tail-),但是为了实现恒定的空间使用,您需要依靠编译器来优化tail递归,它消耗的辅助空间与两个子数组中较大者与较小者的长度比成比例。

    因此
    leftArr
    rightArr
    始终指向以
    byteArr
    开头的同一内存块的某个位置。看起来代码可以以
    void foo开头(char*byteArr,unsigned lStart,unsigned rStart,unsigned leftArrLen,unsigned rightArrLen);
    @chux推导得很好(在你删除的答案中),但如果不知道char*byteArr的长度,就会有危险,因为它是一个缺少的函数参数。@WeatherVane虽然真的
    byteArr
    没有长度,但它实际上只是就我而言,“足够长了”。可以假定
    left+left_length
    在恒定空间中肯定有效,但最坏情况下的时间复杂度似乎比在步骤1之后简单地旋转要糟糕得多(我不确定这一点),我相信这将使用恒定空间。啊,我的错,它是
    O(n+m)
    因为每次交换/移动都涉及到将元素移动到正确的位置。我同意您的分析。事实上,如果我将n作为左右数组的组合大小,我认为我的算法的工作量受O(n)的限制,用旋转替换步骤2和步骤3并不能提供更严格的界限。我倾向于同意旋转选项可能具有更低的系数,但我注意到,在特殊情况下,这两个选项实际上是相同的,即左右数组具有相同的长度,并且没有间隙。根据缓存,swappi由于地理位置的原因,ng可能比轮换快得多。如果您希望这样做,我不反对。但是您的代表级别不够高,无法在没有审阅的情况下进行编辑,审阅者很有可能拒绝此类编辑。
    bool testAlign(int lStart, int lLength, int rStart, int rLength)
    {
        char* byteArr = (char*) malloc(100 * sizeof(char));
        char* leftArr = byteArr + lStart;
        char* rightArr = byteArr + rStart;
        for(int i = 0; i < rLength; i++)
        {
            rightArr[i] = i;
        }
        for(int i = 0; i < lLength; i++)
        {
            leftArr[i] = i + rLength;
        }
        align(byteArr, leftArr, lLength, rightArr, rLength);
        for(int i = 0; i < lLength + rLength; i++)
        {
            if(byteArr[i] != i) return false;
        }
        return true;
    }
    
    X1 Left X2 Right |---|--------|---|------| R1 Left X2' R2 |---|--------|------|---| R1' X2'' Left R2' |------|-----|-------|--| R1' L2 X2'' L1 |------|---|-------|----|