C#指针、迭代器和泛型

C#指针、迭代器和泛型,c#,c++,generics,collections,iterator,C#,C++,Generics,Collections,Iterator,我被难住了 我如何在C++中使用迭代器,像C++迭代器?我找不到Begin()或End()访问器,甚至找不到如何声明迭代器。我读过关于Ienumerator的文章。我的目标是实现合并功能。这里是我用C++编写的合并函数的一部分。大多数情况下,我在寻找与所示内容相同的C#等价物,但我将使用引用类型而不是整数 void merge(vector<int>::iterator left, vector<int>::iterator right, vector<int>

我被难住了

<>我如何在C++中使用迭代器,像C++迭代器?我找不到Begin()或End()访问器,甚至找不到如何声明迭代器。我读过关于Ienumerator的文章。我的目标是实现合并功能。这里是我用C++编写的合并函数的一部分。大多数情况下,我在寻找与所示内容相同的C#等价物,但我将使用引用类型而不是整数

void merge(vector<int>::iterator left, vector<int>::iterator right, vector<int>::iterator      leftEnd, vector<int>::iterator rightEnd, vector<int>::iterator full)
{

    while(left != leftEnd && right!= rightEnd) //compare left and right until the end of the vector is reached
    {
        if(*right < *left)      //right < left so insert right to the output vector and advance the iterators
        {
            *full++ = *right++;
        }
        else                   //left < right so insert left to the output vector and advance the iterators
        {
            *full++ = *left++;
        }
    }

    while(left != leftEnd)    //copy any remaining elements into the output from left 
    {
        *full++ = *left++;
    }
}
void合并(向量::迭代器左、向量::迭代器右、向量::迭代器左端、向量::迭代器右端、向量::迭代器全)
{
while(left!=leftEnd&&right!=rightEnd)//比较左右,直到到达向量的末尾
{
if(*right<*left)//right

此外,我应该使用什么集合?(目前我一直在尝试
列表
链接列表
)。

听起来你想要的是:

bool leftValid = left.MoveNext();
bool rightValid = right.MoveNext();

while (leftValid && rightValid)
{
    if (right.Current < left.Current)
    {
        full.Add(right.Current);
        rightValid = right.MoveNext();
    }
    else
    {
        full.Add(left.Current);
        leftValid = left.MoveNext();
    }
}

while (leftValid)
{
    full.Add(left.Current);
    leftValid = left.MoveNext();    
}

while (rightValid)
{
    full.Add(right.Current);
    rightValid = right.MoveNext();    
}
using (IEnumerable<T> leftIterator = leftSequence.GetEnumerator())
{
    using (IEnumerable<T> rightIterator = rightSequence.GetEnumerator())
    {
        // Code as above, just using leftIterator and rightIterator
        // instead of left and right
    }
}

我想您需要GetEnumerator()、MoveNext()和Current

通常,您可以使用foreach进行迭代,但您的情况是特殊的

如果是事实,而不是使用“full”,则将其组织为迭代器块并惰性地合并两个可枚举项

IEnumerable<T> Merge<T>(IEnumerable<T> left, IEnumerable<T> right)
{
    ... yield return Min<T>(left.Current, right.Current); ..,
}
IEnumerable合并(IEnumerable左、IEnumerable右)
{
…最小输出返回值(左.电流,右.电流)。。,
}

> p> .NET容器不支持C++风格迭代器。他们唯一拥有的就是一个

  • 称为
    IEnumerator的简单正向迭代器
  • 无法修改集合的
  • 这不是随机访问吗
  • 无法复制(某些集合具有可以复制的值类型迭代器,但这是一项棘手的工作,很少使用)
  • 在大多数集合上,每当您修改集合时,该集合也会失效
几乎他们唯一能做的就是在
foreach
语句中进行迭代


您可能希望查看允许随机访问的
IList
接口,但该接口仅在支持快速索引的集合上受支持。在这样的集合上,您可以通过使用索引实现就地合并排序

void Merge<T>(IList<T> container,int left, int right, int leftEnd, int rightEnd, int full)
void合并(IList容器、int-left、int-right、int-leftEnd、int-rightEnd、int-full)
然后使用
容器[left]
而不是
*left



<>这是一个不幸的结果,你不能实现一个有效的就地容器无关排序函数,比如C++。

你可以使用数组,它有固定大小,或者List >,也被称为其他语言的数组列表。他们的项目可以通过索引器(
list[i]
)访问,项目可以附加
list.Add(项目)。它们会自动生长<代码>链接列表
无法通过索引器访问,必须遍历

您可以这样声明方法

IEnumerable<int> intEnumerable = ...;
IEnumerator<int> intEnumerator = intEnumerable.GetEnumerator();
void合并(IEnumerator左、IEnumerator右、,
(完整列表)
{
//Jon Skeet的密码在这里
}
你可以得到这样一个枚举器

IEnumerable<int> intEnumerable = ...;
IEnumerator<int> intEnumerator = intEnumerable.GetEnumerator();
IEnumerable intEnumerable=。。。;
IEnumerator intEnumerator=intEnumerable.GetEnumerator();
IEnumerable
由大多数通用集合类型实现。非泛型集合通常实现
IEnumerable


(根据@CodeInChaos的评论编辑)。

请注意,
full
不能是迭代器,因为.NET枚举数是只读的。您必须传入类似于
IList
的内容。@MattiVirkkunen:确实-会注意到这一点。@CodeInChaos:对不起,是的,我会澄清关于不变性的部分。我不知道你说的.NET不支持创建迭代器副本是什么意思-你可以创建一个需要两个
IEnumerator
s的方法,它可以正常工作。请注意,使用
IEnumerable
会更有意义。我将对此进行编辑。@jonsket这些迭代器可能都指向同一容器中的不同元素。将它们视为列表中的索引,但处理不支持快速索引的集合。leftSequence.GetEnumerator()和rightSequence.GetEnumerator()是什么?您不是在实现吗?@Serge否,这是合并排序的合并部分。注意
if(*right<*left)
没有可传递到
left
/
right
的枚举项。这些是部分迭代迭代器的副本。我不认为您的编辑解决了这个问题。这些迭代器可能都指向同一容器中的不同元素。将它们视为列表中的索引,但处理不支持快速索引的集合。
IEnumerator
(而不是
IEnumerable
!)是列表中的一种索引<代码>左侧
右侧
现在可以指向同一集合中的不同位置。(我将它们的类型从
IEnumerable
更改为
IEnumerator
),但(通常)不能复制它们。所以不能按值将它们传递给助手方法。我认为这种复制能力在这种算法中是必要的。我没有意识到
List
将枚举数实现为结构。我现在将它们更改为
ref
参数。如果我们将迭代器定义为保持当前位置并启用导航的集合的方便容器无关句柄,那么.NET支持的唯一迭代器类型就是forward readonly迭代器。真遗憾。在许多非平凡算法中,双向或随机访问迭代器有很多用途。