从时间复杂度上看for,foreach都是O(n),二叉树查询是lg(n)->O(n)
但是为什么foreach总是比树和linq查的快?
然后以后直接写遍历查找就好了,哪里错了,是il优化了吗,foreach怎么说也就是一个迭代器,不管怎么应该都是O(n)啊
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace tree
{
public class Person : IComparable<Person>
{
public string Name { get; set; }
public int Id { get; set; }
public int Age { get; set; }
public Person()
{
}
public Person(string name, int id, int age)
{
this.Name = name;
this.Id = id;
this.Age = age;
}
public override bool Equals(object obj)
{
if (obj is Person)
{
var o = obj as Person;
if (o.Name == Name
&& o.Id == Id
&& o.Age == Age)
{
return true;
}
}
return false;
}
public override int GetHashCode()
{
return Id;
}
public override string ToString()
{
return $"Id:{Id} Name:{Name} Age:{Age}";
}
public int CompareTo(Person other)
{
if (Equals(other))
{
return 0;
}
else if (other.Age > this.Age)
{
return 1;
}
return -1;
}
}
public class BinarySearchTree
{
public BinarySearchTree Left { get; set; }
public BinarySearchTree Right { get; set; }
public Person Data { get; set; }
public BinarySearchTree(Person p)
{
this.Data = p;
}
public BinarySearchTree(string data, int id, int age)
{
Data = new Person() { Name = data, Id = id, Age = age };
}
public void AddNode(int type, BinarySearchTree tree)
{
if (tree == null)
{
throw new Exception("root is null");
}
switch (type)
{
case 0:
Left = tree;
break;
case 1:
Right = tree;
break;
}
}
public void Display(BinarySearchTree tree, int type)
{
if (tree == null)
{
return;
}
else
{
if (type == 1)
{
System.Console.Write($"{tree.Data.Name}-{tree.Data.Id}-{tree.Data.Age} ");
Display(tree.Left, 1);
Display(tree.Right, 1);
}
else if (type == 2)
{
Display(tree.Left, 2);
System.Console.Write($"{tree.Data.Name}-{tree.Data.Id}-{tree.Data.Age} ");
Display(tree.Right, 2);
}
else if (type == 3)
{
Display(tree.Left, 3);
Display(tree.Right, 3);
System.Console.Write($"{tree.Data.Name}-{tree.Data.Id}-{tree.Data.Age} ");
}
}
}
public BinarySearchTree Search(BinarySearchTree tree, Person data)
{
BinarySearchTree p;
if (tree == null)
{
return null;
}
else
{
if (tree.Data.Equals(data))
{
return tree;
}
if ((p = Search(tree.Left, data)) != null)
{
return p;
}
if ((p = Search(tree.Right, data)) != null)
{
return p;
}
}
return null;
}
public int Height(BinarySearchTree tree)
{
int dep1 = 0, dep2 = 0;
if (tree == null)
{
return 0;
}
dep1 = Height(tree.Left);
dep2 = Height(tree.Right);
return (dep1 > dep2 ? dep1 + 1 : dep2 + 1);
}
public BinarySearchTree Convert(BinarySearchTree tree, List<Person> datas, int start = 1)
{
if (tree == null)
return null;
if (datas.Count == 0)
return tree;
if (start < datas.Count)
{
int l = start, r = start + 1;
if (start + 1 < datas.Count)
tree.Left = new BinarySearchTree(datas[l]);
if (start + 1 < datas.Count)
tree.Right = new BinarySearchTree(datas[r]);
Convert(tree.Left, datas, 2 * l + 1);
Convert(tree.Right, datas, 2 * r + 1);
}
return tree;
}
public override string ToString()
{
return Data.ToString();
}
}
public class TreeTest
{
public static Tuple<BinarySearchTree, List<Person>> InitTest()
{
List<Person> list = new List<Person>()
{
};
for (int i = 1; i < 1000000; i++)
{
list.Add(new Person()
{
Age = 20 + i % 20,
Id = 0,
Name = "p" + ('a' + i)
});
}
BinarySearchTree tree = new BinarySearchTree(list[0]);
tree.Convert(tree, list, 1);
return new Tuple<BinarySearchTree, List<Person>>(tree, list);
}
public static void Test()
{
var data = InitTest();
var tree = data.Item1;
var list = data.Item2;
var last = list[list.Count - 1000];
var p = last;
WriteTime("foreach", () =>
{
foreach (var it in list)
{
if (p == it)
{
return p;
}
}
return null;
});
WriteTime("for", () =>
{
for (int i = 0; i < list.Count; i++)
{
if (p == list[i])
{
return p;
}
}
return null;
});
WriteTime("linq", () => list.First(s => s.Equals(last)));
WriteTime("search", () => tree.Search(tree, p));
var item = tree.Search(tree, p);
if (item == null)
{
System.Console.WriteLine($"not found {p}");
}
else
{
System.Console.WriteLine($"{item}");
}
System.Console.WriteLine(tree.Height(tree));
}
public static void WriteTime(string desc, Func<object> func)
{
Stopwatch sw = new Stopwatch();
sw.Start();
System.Console.WriteLine($"{desc}-- {func()}");
sw.Stop();
System.Console.WriteLine(sw.Elapsed);
}
}
}
循环肯定比递归块.因为递归的损耗是非常大的.
所以遍历最快的方法就是循环.
老夫写代码从来不管什么复杂度,拿起键盘就是一阵梭