关于将指针作为参数传递,我不理解什么?

时间:2014-01-08 05:37:32

标签: c++

我做了以下一些代码来将零移动到数组的前面(顺便说一句,是否有更优雅高效的程序?)。出于某种原因,当我测试函数时,它不会修改数组,就像它应该做的那样。我无法弄清楚出了什么问题。

void zeros_to_front(int* arr, int sz) { 
    std::vector<int> nonzeroesVec;
    for (int k = 0; k < sz; ++k) { 
        if (arr[k] != 0) 
            nonzeroesVec.push_back(arr[k]);
    }
    int numzeroes = sz - nonzeroesVec.size();
    int j(0), k(0);
    while (j < numzeroes) 
        arr[j++] = 0;
    while (j < sz)
        arr[j++] = nonzeroesVec[k++];
}   

3 个答案:

答案 0 :(得分:2)

如果您以后不关心非零元素的顺序,可以使用:

void swap(int& x, int& y)
{
    x ^= y;
    y ^= x;
    x ^= y;
}    

void zerosToFront(int arr[], int size)
{
    if(size < 1)
    {
        return;
    }

    int front = 0;
    for(int i = 0; i < size; i++)
    {
        if(arr[i] == 0)
        {
            swap(arr[i], arr[front++]);
        }
    }
}

它在数组中迭代一次,每当它找到零时,它就会将零交换到数组的前面。它是O(n),效率最高。

但是,如果您 关心订单,可以使用

void zerosToFront(int arr[], int size)
{
    if(size < 1)
    {
        return;
    }

    for(int i = 0; i < size; i++)
    {
        if(arr[i] == 0)
        {
            for(int j = 0; j < i; j++)
            {
                swap(arr[i - j], arr[i - j- 1]);
            }
        }
    }
}

这会遍历数组一次,每当它找到零时,内部for循环基本上会将我们找到的零之前的所有内容移到右边,以便为列表开头的零腾出空间。但是,由于内部for循环,这是O(n^2),因此效率较低。但是对于相对较小的阵列,您不会注意到性能差异。

修改: 实际上,我刚刚意识到一些有趣的事情。如果向后遍历数组,则可以将零推到前面并在O(n)时间内保留非零元素的排序。

void ztf(int arr[], int size)
{
    if(size < 1)
    {
        return;
    }

    int back = size - 1;
    for(int i = size - 1; i >= 0; i--)
    {
        if(arr[i] != 0)
        {
            arr[back--] = arr[i];
        }
    }

    while(back >= 0)
    {
        arr[back--] = 0;
    }
}

只是觉得那太漂亮了。

答案 1 :(得分:1)

无论症状如何,我似乎无法重现它:

#include <stdio.h>
#include <vector>

void zeros_to_front(int* arr, int sz) { 
    std::vector<int> nonzeroesVec;
    for (int k = 0; k < sz; ++k) { 
        if (arr[k] != 0) 
            nonzeroesVec.push_back(arr[k]);
    }
    int numzeroes = sz - nonzeroesVec.size();
    int j(0), k(0);
    while (j < numzeroes) 
        arr[j++] = 0;
    while (j < sz)
        arr[j++] = nonzeroesVec[k++];
}   

int main(int argc,char *argv[])
{
    int ptr[5] = {0};
    ptr[0] = 1;
    zeros_to_front(ptr,5);
    for (int i = 0;i < 5;++i){
        printf("%d",ptr[i]);
    }
    return 0;
}

按预期工作并打印出“00001”。

答案 2 :(得分:0)

我建议这样的事情:

#include <vector>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <iterator>

void
shake(int * arr, std::size_t N)
{
    bool changed;
    do
    {
        changed = false;
        for (std::size_t i = 0; i != N - 1; ++i)
        {
            if (arr[i + 1] == 0 && arr[i] != 0)
            {
                std::swap(arr[i], arr[i + 1]);
                changed = true;                
            }
        }
    }
    while (changed);
}

int
main ()
{
    std::vector<int> vec { 1, 0, 2, 0, 3, 0, 0, 4, 5, 0 };
    shake(&vec[0], vec.size());
    std::copy(vec.begin(), vec.end(),
        std::ostream_iterator<int>(std::cout, ", "));
}