首页 新闻 会员 周边 捐助

时间复杂度上为什么foreach比二叉树要快呢?

0
[已解决问题] 解决于 2017-07-03 19:15

从时间复杂度上看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);
    }
}

}

给我一个理由的主页 给我一个理由 | 初学一级 | 园豆:17
提问于:2017-07-03 12:53
< >
分享
最佳答案
1

循环肯定比递归块.因为递归的损耗是非常大的.

所以遍历最快的方法就是循环.

奖励园豆:5
吴瑞祥 | 高人七级 |园豆:29449 | 2017-07-03 13:17
其他回答(1)
0

老夫写代码从来不管什么复杂度,拿起键盘就是一阵梭

~扎克伯格 | 园豆:1923 (小虾三级) | 2017-07-03 13:04
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册