আমি কোন গাছকে পুনরাবৃত্তি না করে কীভাবে অতিক্রম করব?


19

আমার মেমরি নোড ট্রি খুব বড় এবং গাছটি পেরোতে হবে। প্রতিটি সন্তানের নোডের ফিরে আসা মানগুলি তাদের প্যারেন্ট নোডে পাস করা। সমস্ত নোডের রুট নোড পর্যন্ত তাদের ডেটা বুদবুদ না হওয়া পর্যন্ত এটি করতে হবে।

ট্র্যাভারসাল এটির মতো কাজ করে।

private Data Execute(Node pNode)
{
    Data[] values = new Data[pNode.Children.Count];
    for(int i=0; i < pNode.Children.Count; i++)
    {
        values[i] = Execute(pNode.Children[i]);  // recursive
    }
    return pNode.Process(values);
}

public void Start(Node pRoot)
{
    Data result = Execute(pRoot);
}

এটি ঠিকঠাক কাজ করে, তবে আমি উদ্বিগ্ন যে কল স্ট্যাক নোড গাছের আকারকে সীমাবদ্ধ করে।

কোডটি কীভাবে পুনর্লিখন করা যায় যাতে কোনও পুনরাবৃত্ত কল করা না Executeযায়?


8
নোডগুলি ট্র্যাক রাখতে আপনার নিজের স্ট্যাক বজায় রাখতে হবে, বা গাছের আকৃতি পরিবর্তন করতে হবে। দেখুন stackoverflow.com/q/5496464 এবং stackoverflow.com/q/4581576
রবার্ট হার্ভে

1
আমি এই গুগল অনুসন্ধানে বিশেষত মরিস ট্র্যাভারসালকেও প্রচুর সহায়তা পেয়েছি ।
রবার্ট হার্ভে

@ রবার্টহারভে রবকে ধন্যবাদ জানায়, আমি নিশ্চিত ছিলাম না যে এটি কোন শর্তের আওতায় চলেছে।
প্রতিক্রিয়া

2
আপনি যদি গণিতটি করেন তবে আপনি মেমরির প্রয়োজনীয়তাগুলি দেখে অবাক হতে পারেন। উদাহরণস্বরূপ, পুরোপুরি সুষম টেরানোড বাইনারি গাছের জন্য কেবল 40 টি প্রবেশপথ গভীর স্ট্যাকের প্রয়োজন।
কার্ল বিলেফেল্ট 21

@ কার্লবিলিফেল্ড এটি ধরে নিচ্ছে যে গাছটি পুরোপুরি সুষম। কখনও কখনও আপনার গাছগুলিকে মডেলিং করা দরকার যা ভারসাম্যহীন নয় এবং সেক্ষেত্রে স্ট্যাকটি ফুঁ দেওয়া খুব সহজ।
পরিবেশন করুন

উত্তর:


27

এখানে একটি সাধারণ উদ্দেশ্যে ট্রি ট্রভারসাল বাস্তবায়ন যা পুনরাবৃত্তি ব্যবহার করে না:

public static IEnumerable<T> Traverse<T>(T item, Func<T, IEnumerable<T>> childSelector)
{
    var stack = new Stack<T>();
    stack.Push(item);
    while (stack.Any())
    {
        var next = stack.Pop();
        yield return next;
        foreach (var child in childSelector(next))
            stack.Push(child);
    }
}

আপনার ক্ষেত্রে আপনি এটিকে এভাবে কল করতে পারেন:

IEnumerable<Node> allNodes = Traverse(pRoot, node => node.Children);

প্রথমে গভীরতার পরিবর্তে প্রথমে শ্বাসের Queueপরিবর্তে একটি ব্যবহার করুন Stack, অনুসন্ধান করুন। PriorityQueueসেরা প্রথম অনুসন্ধানের জন্য একটি ব্যবহার করুন ।


আমি কি এই ভেবে সঠিক হয়েছি যে এটি কেবল গাছটিকে একটি সংগ্রহের মধ্যে চ্যাপ্টা করবে?

1
@ ম্যাথিউফস্কারিনী হ্যাঁ, এটিই এর উদ্দেশ্য। অবশ্যই, এটি অগত্যা একটি আসল সংগ্রহ হিসাবে রূপায়িত করা প্রয়োজন হবে না। এটি কেবল একটি ক্রম। মেমরির পুরো সেট সেটটি টানানোর প্রয়োজন ছাড়াই আপনি ডেটা স্ট্রিম করতে এর উপরে পুনরাবৃত্তি করতে পারেন।
পরিবেশন করুন

আমি মনে করি না যে সমস্যার সমাধান করে।
চুল্লী

4
তিনি কেবল অনুসন্ধানের মতো স্বাধীন ক্রিয়াকলাপ সম্পাদন করে গ্রাফটি অতিক্রম করছেন না, তিনি শিশু নোডগুলি থেকে ডেটা একত্রিত করছেন। গাছটি সমতল করা সমষ্টি সম্পাদনের জন্য তার প্রয়োজনীয় কাঠামোর তথ্য নষ্ট করে দেয়।
কার্ল বিলেফেল্ট

1
এফওয়াইআই আমি মনে করি যে এটি সঠিক উত্তর বেশিরভাগ লোকেরা এই প্রশ্নটি খুঁজছেন। +1
আন্ডার্স আরপী

4

আপনার গাছের গভীরতার জন্য যদি আপনার আগে থেকে অনুমান থাকে তবে সম্ভবত আপনার ক্ষেত্রে স্ট্যাকের আকারটি মানিয়ে নেওয়া যথেষ্ট? সংস্করণ ২.০ থেকে সি # তে আপনি যখনই নতুন থ্রেড শুরু করবেন এটি সম্ভব, এখানে দেখুন:

http://www.atalasoft.com/cs/blogs/rickm/archive/2008/04/22/increasing-the-size-of-your-stack-net-memory-management-part-3.aspx

এইভাবে আপনি আরও জটিল কিছু প্রয়োগ না করেই আপনার পুনরাবৃত্তির কোডটি রাখতে পারেন। অবশ্যই, আপনার নিজের স্ট্যাকের সাথে একটি পুনরাবৃত্ত সমাধান সমাধান করা আরও সময় এবং মেমরির দক্ষ হতে পারে, তবে আমি নিশ্চিত যে কোডটি এখনকার মতো সহজ হবে না।


আমি কেবল একটি দ্রুত পরীক্ষা করেছি made আমার মেশিনে আমি স্ট্যাকওভারফ্লোতে পৌঁছানোর আগে 14000 পুনরাবৃত্ত কল করতে পারি। গাছটি সুষম হলে 4 বিলিয়ন নোড সংরক্ষণের জন্য কেবল 32 টি কল প্রয়োজন। প্রতিটি নোডটি যদি 1 বাইট হয় (যা এটি হবে না) তবে 32 উচ্চতার ভারসাম্যযুক্ত গাছ সংরক্ষণ করতে 4 জিবি র‌্যাম লাগবে
এসেনভেন স্কোভ পেদারসেন

আমি স্ট্যাকের মধ্যে সমস্ত 14000 কল ব্যবহার করব। গাছে প্রতিটি নোড এক বাইট (যা এটি হবে না) হলে 2.6x10 ^ 4214 বাইট উঠতে পারে
এসবেন স্কোভ পেদারসেন

-3

আপনি পুনরাবৃত্তি না করে গাছের আকারে কোনও ডেটা স্ট্রাকচার অতিক্রম করতে পারবেন না - আপনি যদি আপনার ভাষার দ্বারা সরবরাহিত স্ট্যাক ফ্রেম এবং ফাংশন কলগুলি ব্যবহার না করেন তবে আপনাকে মূলত আপনার নিজের স্ট্যাক এবং ফাংশন কলগুলি প্রোগ্রাম করতে হবে এবং এটি হ'ল অসম্ভাব্য যে আপনার এটা পরিচালনা মধ্যে আরো কার্যকর পদ্ধতিতে পথ কম্পাইলার লেখক চেয়ে যন্ত্র যা আপনার প্রোগ্রাম চালানো হবে করেনি ভাষা।

সুতরাং, সম্পদের সীমাতে চলে যাওয়ার ভয়ে পুনরাবৃত্তি এড়ানো সাধারণত ভুল পথে চালিত হয়। নিশ্চিত হতে যে, অকালীন উত্স অপ্টিমাইজেশন সর্বদা বিপথগামী হয় তবে এই ক্ষেত্রে সম্ভবত আপনি মেমরির ব্যবহারের বাধা হ'ল এটি পরিমাপ করে এবং নিশ্চিত করেও আপনি সম্ভবত এটির স্তরে নামা ছাড়াই উন্নত করতে পারবেন না সংকলক লেখক।


2
এটা সহজ মিথ্যা। পুনরাবৃত্তি না ব্যবহার করে কোনও গাছকে অতিক্রম করা খুব সম্ভবত সম্ভব। এটা এমনকি কঠিন না । আপনি আরও দক্ষতার সাথে, বেশ তুচ্ছভাবেও করতে পারেন, কারণ আপনি কেবল স্পষ্টতামূলক স্ট্যাকের মধ্যে যথাসম্ভব তথ্য অন্তর্ভুক্ত করতে পারেন যতটা নিশ্চিত যে আপনার নির্দিষ্ট ট্র্যাভারসালের জন্য আপনার প্রয়োজন, অন্যদিকে পুনরাবৃত্তিটি ব্যবহার করে আপনি অনেকগুলি প্রয়োজনের তুলনায় আরও তথ্য সঞ্চিত করেন মামলা।
পরিবেশন করুন

2
এই বিতর্কটি এখানে একবারে একবারে উঠে আসে। কিছু পোস্টার আপনার নিজস্ব স্ট্যাক ঘূর্ণায়মান হিসাবে বিবেচনা না করা বিবেচনা করে, অন্যরা নির্দেশ করে যে তারা কেবল একই কাজটি স্পষ্টভাবে করছে যে রানটাইম অন্যথায় স্পষ্টভাবে করবে। এই জাতীয় সংজ্ঞা নিয়ে তর্ক করার কোনও অর্থ নেই।
কিলিয়ান ফট

আপনি কীভাবে পুনরাবৃত্তি সংজ্ঞায়িত করবেন? আমি এটিকে এমন একটি ফাংশন হিসাবে সংজ্ঞায়িত করব যা নিজের সংজ্ঞায়নের মধ্যে নিজেকে ডাকে। আমার জবাব হিসাবে আমি যেটা দেখিয়েছি তা আপনি কখনও তা না করেই অবশ্যই কোনও গাছের মধ্যে যেতে পারেন।
পরিবেশন করুন

2
এ জাতীয় উচ্চমানের স্কোর সহকারে ডাউনটাতে ক্লিক করার কাজটি উপভোগ করার জন্য আমি কি মন্দ? এটি এই ওয়েবসাইটে একটি বিরল আনন্দ।
প্রতিক্রিয়া

2
আসুন @ ম্যাট, এটি বাচ্চাদের জিনিস। আপনি দ্বিমত পোষণ করতে পারেন, যেমন আপনি যদি খুব গভীর যে গাছে বোমা ফেলার ভয় পান তবে এটি যুক্তিসঙ্গত উদ্বেগ। আপনি ঠিক তাই বলতে পারেন।
মাইক ডুনলাভে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.