那么时间复杂度是多少?100N?....
!!):迭代器 是不是与指针有关..比如存储数据: 是通过指针++来逐步存储数据的...迭代器这个请详细解释下;;;
!!!):yield return a 是不是就是在当前迭代快中 add a 这个值 啊.....
假如是这样的话,我完全可以用List<T> 这样的链表来代替啊... for(i....) list[T] 实例.add(值)..那么迭代器感觉可以不需要啊
14 个解决方案
#1
注意你的用词,O(n)和O(N)是不同的。
yield return本质上是一个状态机,C#会创建一个线程,并且每次迭代后都会将这个线程挂起,再次调用则继续。它向调用者返回当前迭代值,但是它不会保存到存储中,和List不同,也不能随机访问迭代器。
yield return本质上是一个状态机,C#会创建一个线程,并且每次迭代后都会将这个线程挂起,再次调用则继续。它向调用者返回当前迭代值,但是它不会保存到存储中,和List不同,也不能随机访问迭代器。
#2
第3个问题解决了 3Q .. 1 ,2 问题 求继续解答.. .注意你的用词,O(n)和O(N)是不同的。这个啥意思?
#3
之前我说错了,O(n)和o(n)是不同的。
O(n)表示的是函数数量级的渐近上界。因此100N这个说法是不对的,不应该有常数项。
O(n)表示的是函数数量级的渐近上界。因此100N这个说法是不对的,不应该有常数项。
#4
“那么时间复杂度是多少?100N?....” --- 1
不需要循环,直接取值,因为它有一个栈顶指针啊,任何时候操作都是在栈顶
不需要循环,直接取值,因为它有一个栈顶指针啊,任何时候操作都是在栈顶
#5
用yield的好处是你可以再迭代的时候同时完成其他操作 效率更高
#6
用yield的好处是你可以再迭代的时候同时完成其他操作 效率更高
#7
但是当前 栈顶执行完之后 必须的 drop()才行啊,,假如这个时间复杂度为 O(n),.递归一百次 时间复杂度为100 O(n)对不对?
#8
可以这么理解么??实际上就是一小段内存,在foreach的时候,取当前值.假如foreach执行完了第一次了.这段内存就清空,然后在第二次的时候,把取到的值,放到内存中去??
#9
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class OneToThree : IEnumerable<int>
{
public class OneToThreeEnumerator : IEnumerator<int>, IEnumerator
{
private int _current = 0;
public int Current
{
get { return _current; }
}
public void Dispose()
{
//这里我们不需要清理
}
object System.Collections.IEnumerator.Current
{
get { return _current; }
}
public bool MoveNext()
{
_current++;
return _current <= 3;
}
public void Reset()
{
_current = 0;
}
}
public IEnumerator<int> GetEnumerator()
{
return new OneToThree.OneToThreeEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new OneToThree.OneToThreeEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
foreach (int x in new OneToThree())
{
Console.WriteLine(x);
}
}
}
}
对照yield return
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
//这个方法会创建一个匿名迭代器类,等价之前的代码
static IEnumerable<int> GetOneToThreeClass()
{
int _current = 1;
while (_current <= 3)
{
yield return _current++;
}
}
static void Main(string[] args)
{
foreach (int x in GetOneToThreeClass())
{
Console.WriteLine(x);
}
}
}
}
#10
class Program
{
//这个方法会创建一个匿名迭代器类,等价之前的代码
static IEnumerable<int> GetOneToThreeClass()
{
int _current = 1;
while (_current <= 3)
{
yield return _current++;
}
}
static void Main(string[] args)
{
GetOneToThreeClass();//疑问1;
GetOneToThreeClass().ToArray();//疑问2
foreach (int x in GetOneToThreeClass())
{
Console.WriteLine(x);
}
}
}
我不明白的就是这个...
在疑问1 和疑问2 以及GetOneToThreeClass() 打好断点..
在执行疑问1的时候不会跟到GetOneToThreeClass()中去..
执行疑问2的时候就跟到GetOneToThreeClass()中去了..
这个有点想不通..这个应该就是和yield 有关的吧?
#11
就是在疑问1处的时候他并不存储数据..
到疑问2 toarry()的时候.需要数组来保存的时候才去读数据处理数据.?这个是不是就是yield的延迟特性?
到疑问2 toarry()的时候.需要数组来保存的时候才去读数据处理数据.?这个是不是就是yield的延迟特性?
#12
人了???
#13
这个问题说来话长,这次我再展开foreach,看看你能不能琢磨出什么。
对照
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class OneToThree : IEnumerable<int>
{
public class OneToThreeEnumerator : IEnumerator<int>, IEnumerator
{
private int _current = 0;
public int Current
{
get { return _current; }
}
public void Dispose()
{
//这里我们不需要清理
}
object System.Collections.IEnumerator.Current
{
get { return _current; }
}
public bool MoveNext()
{
_current++;
return _current <= 3;
}
public void Reset()
{
_current = 0;
}
}
public IEnumerator<int> GetEnumerator()
{
return new OneToThree.OneToThreeEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new OneToThree.OneToThreeEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
var onetothreeclass = new OneToThree();
var itor = onetothreeclass.GetEnumerator();
while (itor.MoveNext())
{
Console.WriteLine(itor.Current);
}
}
}
}
对照
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static IEnumerable<int> GetOneToThreeClass()
{
int _current = 1;
while (_current <= 3)
{
yield return _current++;
}
}
static void Main(string[] args)
{
var onetothreeclass = GetOneToThreeClass();
var itor = onetothreeclass.GetEnumerator();
while (itor.MoveNext())
{
Console.WriteLine(itor.Current);
}
}
}
}
#14
一般来说,一个函数的调用过程是,将调用者的地址保存,参数压入堆栈,函数执行,然后恢复堆栈,返回结果,转到调用者继续执行。
而yield return则可以自动产生一个匿名类,这个类的迭代器的current和movenext方法有些不同——它会将你的原来yield return的那个方法“拆开来”,使得它可以分段执行——在每次movenext被调用的时候,这个函数就会执行,直到遇到yield return,它会把函数的当前状态保存下来,并且挂起执行(事实上内部是用了一个线程)。当调用current的时候,就返回yield return的内容。当再次调用movenext的时候,就会恢复之前的函数调用,运行直到再次遇到yield return或者运行完,如果是运行到yield return,和之前说的一样,如果运行完也没有遇到yield return,movenext就会返回false。
为什么说这个过程是延迟执行的——很容易理解。因为当你遍历的时候,只有在调用movenext时候,这个函数才会执行一小部分,而不是像list那样,先运行完成,得到所有结果,装入内存,再开始迭代。
而yield return则可以自动产生一个匿名类,这个类的迭代器的current和movenext方法有些不同——它会将你的原来yield return的那个方法“拆开来”,使得它可以分段执行——在每次movenext被调用的时候,这个函数就会执行,直到遇到yield return,它会把函数的当前状态保存下来,并且挂起执行(事实上内部是用了一个线程)。当调用current的时候,就返回yield return的内容。当再次调用movenext的时候,就会恢复之前的函数调用,运行直到再次遇到yield return或者运行完,如果是运行到yield return,和之前说的一样,如果运行完也没有遇到yield return,movenext就会返回false。
为什么说这个过程是延迟执行的——很容易理解。因为当你遍历的时候,只有在调用movenext时候,这个函数才会执行一小部分,而不是像list那样,先运行完成,得到所有结果,装入内存,再开始迭代。
#1
注意你的用词,O(n)和O(N)是不同的。
yield return本质上是一个状态机,C#会创建一个线程,并且每次迭代后都会将这个线程挂起,再次调用则继续。它向调用者返回当前迭代值,但是它不会保存到存储中,和List不同,也不能随机访问迭代器。
yield return本质上是一个状态机,C#会创建一个线程,并且每次迭代后都会将这个线程挂起,再次调用则继续。它向调用者返回当前迭代值,但是它不会保存到存储中,和List不同,也不能随机访问迭代器。
#2
第3个问题解决了 3Q .. 1 ,2 问题 求继续解答.. .注意你的用词,O(n)和O(N)是不同的。这个啥意思?
#3
之前我说错了,O(n)和o(n)是不同的。
O(n)表示的是函数数量级的渐近上界。因此100N这个说法是不对的,不应该有常数项。
O(n)表示的是函数数量级的渐近上界。因此100N这个说法是不对的,不应该有常数项。
#4
“那么时间复杂度是多少?100N?....” --- 1
不需要循环,直接取值,因为它有一个栈顶指针啊,任何时候操作都是在栈顶
不需要循环,直接取值,因为它有一个栈顶指针啊,任何时候操作都是在栈顶
#5
用yield的好处是你可以再迭代的时候同时完成其他操作 效率更高
#6
用yield的好处是你可以再迭代的时候同时完成其他操作 效率更高
#7
但是当前 栈顶执行完之后 必须的 drop()才行啊,,假如这个时间复杂度为 O(n),.递归一百次 时间复杂度为100 O(n)对不对?
#8
可以这么理解么??实际上就是一小段内存,在foreach的时候,取当前值.假如foreach执行完了第一次了.这段内存就清空,然后在第二次的时候,把取到的值,放到内存中去??
#9
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class OneToThree : IEnumerable<int>
{
public class OneToThreeEnumerator : IEnumerator<int>, IEnumerator
{
private int _current = 0;
public int Current
{
get { return _current; }
}
public void Dispose()
{
//这里我们不需要清理
}
object System.Collections.IEnumerator.Current
{
get { return _current; }
}
public bool MoveNext()
{
_current++;
return _current <= 3;
}
public void Reset()
{
_current = 0;
}
}
public IEnumerator<int> GetEnumerator()
{
return new OneToThree.OneToThreeEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new OneToThree.OneToThreeEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
foreach (int x in new OneToThree())
{
Console.WriteLine(x);
}
}
}
}
对照yield return
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
//这个方法会创建一个匿名迭代器类,等价之前的代码
static IEnumerable<int> GetOneToThreeClass()
{
int _current = 1;
while (_current <= 3)
{
yield return _current++;
}
}
static void Main(string[] args)
{
foreach (int x in GetOneToThreeClass())
{
Console.WriteLine(x);
}
}
}
}
#10
class Program
{
//这个方法会创建一个匿名迭代器类,等价之前的代码
static IEnumerable<int> GetOneToThreeClass()
{
int _current = 1;
while (_current <= 3)
{
yield return _current++;
}
}
static void Main(string[] args)
{
GetOneToThreeClass();//疑问1;
GetOneToThreeClass().ToArray();//疑问2
foreach (int x in GetOneToThreeClass())
{
Console.WriteLine(x);
}
}
}
我不明白的就是这个...
在疑问1 和疑问2 以及GetOneToThreeClass() 打好断点..
在执行疑问1的时候不会跟到GetOneToThreeClass()中去..
执行疑问2的时候就跟到GetOneToThreeClass()中去了..
这个有点想不通..这个应该就是和yield 有关的吧?
#11
就是在疑问1处的时候他并不存储数据..
到疑问2 toarry()的时候.需要数组来保存的时候才去读数据处理数据.?这个是不是就是yield的延迟特性?
到疑问2 toarry()的时候.需要数组来保存的时候才去读数据处理数据.?这个是不是就是yield的延迟特性?
#12
人了???
#13
这个问题说来话长,这次我再展开foreach,看看你能不能琢磨出什么。
对照
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class OneToThree : IEnumerable<int>
{
public class OneToThreeEnumerator : IEnumerator<int>, IEnumerator
{
private int _current = 0;
public int Current
{
get { return _current; }
}
public void Dispose()
{
//这里我们不需要清理
}
object System.Collections.IEnumerator.Current
{
get { return _current; }
}
public bool MoveNext()
{
_current++;
return _current <= 3;
}
public void Reset()
{
_current = 0;
}
}
public IEnumerator<int> GetEnumerator()
{
return new OneToThree.OneToThreeEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new OneToThree.OneToThreeEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
var onetothreeclass = new OneToThree();
var itor = onetothreeclass.GetEnumerator();
while (itor.MoveNext())
{
Console.WriteLine(itor.Current);
}
}
}
}
对照
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static IEnumerable<int> GetOneToThreeClass()
{
int _current = 1;
while (_current <= 3)
{
yield return _current++;
}
}
static void Main(string[] args)
{
var onetothreeclass = GetOneToThreeClass();
var itor = onetothreeclass.GetEnumerator();
while (itor.MoveNext())
{
Console.WriteLine(itor.Current);
}
}
}
}
#14
一般来说,一个函数的调用过程是,将调用者的地址保存,参数压入堆栈,函数执行,然后恢复堆栈,返回结果,转到调用者继续执行。
而yield return则可以自动产生一个匿名类,这个类的迭代器的current和movenext方法有些不同——它会将你的原来yield return的那个方法“拆开来”,使得它可以分段执行——在每次movenext被调用的时候,这个函数就会执行,直到遇到yield return,它会把函数的当前状态保存下来,并且挂起执行(事实上内部是用了一个线程)。当调用current的时候,就返回yield return的内容。当再次调用movenext的时候,就会恢复之前的函数调用,运行直到再次遇到yield return或者运行完,如果是运行到yield return,和之前说的一样,如果运行完也没有遇到yield return,movenext就会返回false。
为什么说这个过程是延迟执行的——很容易理解。因为当你遍历的时候,只有在调用movenext时候,这个函数才会执行一小部分,而不是像list那样,先运行完成,得到所有结果,装入内存,再开始迭代。
而yield return则可以自动产生一个匿名类,这个类的迭代器的current和movenext方法有些不同——它会将你的原来yield return的那个方法“拆开来”,使得它可以分段执行——在每次movenext被调用的时候,这个函数就会执行,直到遇到yield return,它会把函数的当前状态保存下来,并且挂起执行(事实上内部是用了一个线程)。当调用current的时候,就返回yield return的内容。当再次调用movenext的时候,就会恢复之前的函数调用,运行直到再次遇到yield return或者运行完,如果是运行到yield return,和之前说的一样,如果运行完也没有遇到yield return,movenext就会返回false。
为什么说这个过程是延迟执行的——很容易理解。因为当你遍历的时候,只有在调用movenext时候,这个函数才会执行一小部分,而不是像list那样,先运行完成,得到所有结果,装入内存,再开始迭代。