পুনরাবৃত্তি বা Iteration?


226

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


4
@ ওয়ারিয়র সর্বদা না। দাবা প্রোগ্রামগুলির সাথে, উদাহরণস্বরূপ, পুনরাবৃত্তি পড়া সহজ। দাবা কোডের একটি "পুনরাবৃত্ত" সংস্করণটি সত্যই গতিতে সহায়তা করবে না এবং এটি আরও জটিল করে তুলবে।
মতিন উলহাক

12
কেন একটি হাতুড়ি করাতকে পছন্দ করা উচিত? একটি সার্বক্ষণিক উপর একটি স্ক্রু ড্রাইভার? বাচ্চাদের উপরে একটি ছান?
ওয়েইন কনরাড

3
কোনও পছন্দ নেই। এগুলি হ'ল সমস্ত ন্যায়সঙ্গত সরঞ্জাম, প্রত্যেকে তাদের নিজস্ব উদ্দেশ্য নিয়ে। আমি জিজ্ঞাসা করব, "কোন ধরণের সমস্যা পুনরাবৃত্তির চেয়ে পুনরাবৃত্তির চেয়ে ভাল এবং এর বিপরীতে?"
ওয়েইন কনরাড

9
"রিকার্সন সম্পর্কে কী ভাল?" ... এটি পুনরাবৃত্ত that's ; ও)
কেং

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

উত্তর:


181

এটা সম্ভব যে পুনরাবৃত্তি আরও ব্যয়বহুল হবে তার উপর নির্ভর করে পুনরাবৃত্তি ফাংশনটি টেল রিকার্সিভ (শেষ লাইনটি পুনরাবৃত্তি কল)। লেজ পুনরাবৃত্তি সংকলক দ্বারা স্বীকৃত হওয়া উচিত এবং এর পুনরাবৃত্ত সমকক্ষকে অনুকূল করা উচিত (আপনার কোডটিতে সংক্ষিপ্ত, স্পষ্ট বাস্তবায়ন বজায় রাখার সময়)।

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


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

15
পুনরায়: tail recursion is optimized by compilersতবে সমস্ত সংকলক পুচ্ছ পুনরাবৃত্তি সমর্থন করে না ..
কেভিন মেরিডিথ

347

লুপগুলি আপনার প্রোগ্রামের জন্য পারফরম্যান্স লাভ অর্জন করতে পারে। পুনরাবৃত্তি আপনার প্রোগ্রামারটির জন্য পারফরম্যান্স লাভ অর্জন করতে পারে। আপনার পরিস্থিতিতে কোনটি বেশি গুরুত্বপূর্ণ তা চয়ন করুন!


3
@ লেইক ক্যাল্ডওয়েল: আমি মনে করি যে আমার চিন্তাভাবনাটি ঠিকঠাক করে দিয়েছে। করুণাময় সর্বশক্তিমান আপ আপ না। আমি অবশ্যই আছে। :)
অ্যান্ডি টার্নার

35
আপনি কি জানেন যে আপনার উত্তর বাক্যাংশের কারণে আপনাকে কোনও বইয়ে উদ্ধৃত করা হয়েছিল? LOL amazon.com/Grokking-
pogrammers-

4
আমি এই উত্তরটি পছন্দ করি .. এবং আমি "গ্রোকিং অ্যালগোরিদমস" বইটি পছন্দ করি
ম্যাক্স

সুতরাং, কমপক্ষে আমি এবং 341 জন মানুষ গ্রোক্কিং অ্যালগোরিদম বইটি পড়েন!
zzfima

78

পুনরাবৃত্তির সাথে পুনরাবৃত্তির তুলনা একটি ফিলিপ হেড স্ক্রু ড্রাইভারকে ফ্ল্যাট হেড স্ক্রু ড্রাইভারের সাথে তুলনা করার মতো। অধিকাংশ অংশ জন্য আপনি পারে একটি ফ্ল্যাট মাথা দিয়ে কোনো ফিলিপস মাথা স্ক্রু অপসারণ, কিন্তু এটা শুধু আপনি স্ক্রু ড্রাইভার যে স্ক্রু অধিকার জন্য ডিজাইন করা ব্যবহৃত সহজ হবে?

কিছু অ্যালগোরিদম কেবল তাদের নকশাকৃত নকশার কারণে পুনরাবৃত্তিতে leণ দেয় (ফিবোনাচি সিকোয়েন্সগুলি, কাঠামোর মতো একটি গাছকে অনুসরণ করে ইত্যাদি)। পুনরাবৃত্তি অ্যালগরিদমকে আরও সুসংহত এবং বুঝতে সহজতর করে (তাই ভাগ করে নেওয়া যায় এবং পুনরায় ব্যবহারযোগ্য)।

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

এটি আপনাকে শুরু করার জন্য যথেষ্ট। আমি আপনার জন্য কিছু নিবন্ধ এবং উদাহরণ খনন করব।

লিঙ্ক 1: হাস্কেল বনাম পিএইচপি (পুনরাবৃত্তি বনাম Iteration)

এখানে একটি উদাহরণ যেখানে প্রোগ্রামারকে পিএইচপি ব্যবহার করে একটি বড় ডেটা সেট প্রক্রিয়া করতে হয়েছিল। তিনি দেখান যে পুনরাবৃত্তি ব্যবহার করে হাস্কেলকে মোকাবেলা করা কতটা সহজ হত, কিন্তু পিএইচপি-র একই পদ্ধতিটি সম্পাদন করার সহজ উপায় না থাকায়, ফলাফলটি পেতে তাকে পুনরাবৃত্তি ব্যবহার করতে বাধ্য করা হয়েছিল।

http://blog.webspecies.co.uk/2011-05-31/lazy-evaluation-with-php.html

লিঙ্ক 2: মাস্টারিং পুনরাবৃত্তি

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

"পুনরাবৃত্তিমূলক প্রোগ্রামিং প্রোগ্রামার কোডকে এমনভাবে সংগঠিত করার একটি ভাল উপায় দেয় যা উভয়ই বজায় রাখা যায় এবং যুক্তিযুক্তভাবে সুসংগত হয়" "

https://developer.ibm.com/articles/l-recurs/

লিঙ্ক 3: পুনরাবৃত্তি লুপিংয়ের চেয়ে কখনও দ্রুত হয়? (উত্তর)

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

লুপিংয়ের চেয়ে পুনরাবৃত্তি কি কখনও দ্রুত?


4
স্ক্রু ড্রাইভারের উপমাটি সত্যিই পছন্দ হয়েছে
jh314


16

পুনরাবৃত্তি মেমরিতে আরও ব্যয়বহুল, কারণ প্রতিটি পুনরাবৃত্তির কলকে সাধারণত স্ট্যাকের দিকে ধাক্কা দেওয়ার জন্য একটি মেমরি ঠিকানা প্রয়োজন হয় - যাতে প্রোগ্রামটি সেই পর্যায়ে ফিরে আসতে পারে।

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


5
অবশ্যই আপনার সংকলক স্কালার মতো লেজ কলগুলি অনুকূল করে।
বেন হার্ডি

11

সাধারণত, কেউ পারফরম্যান্সের পেনাল্টিটিকে অন্য দিকে মিথ্যা বলে আশা করবে। পুনরাবৃত্ত কলগুলি অতিরিক্ত স্ট্যাক ফ্রেমগুলি তৈরি করতে পারে; এর জন্য শাস্তি পরিবর্তিত হয়। এছাড়াও, পাইথনের মতো কয়েকটি ভাষায় (আরও সঠিকভাবে, কিছু ভাষার কিছু প্রয়োগে ...), আপনি যে কাজগুলি পুনরাবৃত্তভাবে নির্দিষ্ট করতে পারেন তার জন্য খুব সহজেই স্ট্যাকের সীমাতে চলে যেতে পারেন যেমন একটি ট্রি ডেটা কাঠামোর সর্বোচ্চ মান খুঁজে পাওয়া finding এই ক্ষেত্রে, আপনি সত্যিই লুপের সাথে লেগে থাকতে চান।

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

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


8

পুনরুক্তি একাধিক , ছোট ছোট টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো হয়ে যেতে পারে এমন সমস্যাগুলির জন্য পুনরাবৃত্তির চেয়ে ভাল ।

উদাহরণস্বরূপ, একটি পুনরাবৃত্তিযোগ্য ফিবোনাচি অ্যালগরিদম তৈরি করতে, আপনি ফাইব (এন) কে ফাইব (এন-1) এবং ফাইব (এন -2) মধ্যে বিভক্ত করে উভয় অংশকে গণনা করুন। Iteration কেবল আপনাকে বারবার একক ক্রিয়াকে পুনরাবৃত্তি করতে দেয়।

যাইহোক, ফিবোনাচি আসলে একটি ভাঙা উদাহরণ এবং আমি মনে করি পুনরাবৃত্তি আসলে আরও দক্ষ। লক্ষ্য করুন যে fib (n) = fib (n-1) + fib (n-2) এবং fib (n-1) = fib (n-2) + fib (n-3)। fib (n-1) দ্বিগুণ গণনা করা হয়!

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

সুতরাং হ্যাঁ - পুনরাবৃত্তি একাধিক, ছোট, স্বতন্ত্র, অনুরূপ সমস্যায় বিভক্ত হয়ে যাওয়া সমস্যার জন্য পুনরাবৃত্তির চেয়ে উত্তম।


1
স্মৃতিচারণের মাধ্যমে দুবার গণনাটি এড়ানো যায়।
সিদ্ধার্থ

7

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

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


সর্বদা সত্য হয় না। পুনরাবৃত্তি কিছু ক্ষেত্রে পুনরাবৃত্তি হিসাবে কার্যকর হতে পারে যেখানে টেল কল অপ্টিমাইজেশন করা যায়। stackoverflow.com/questions/310974/…
সিড ক্ষত্রিয়

6

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

http://lambda-the-ultimate.org/node/1333


জাভা জন্য জেভিএম এর রয়েছে যা লেজ-পুনরাবৃত্তি অপ্টিমাইজ করে। আইবিএম.com
জেডিয়াগ

5

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


5

পুনরাবৃত্তি খুব দরকারী কিছু পরিস্থিতিতে। উদাহরণস্বরূপ ফ্যাকটোরিয়াল সন্ধানের কোডটি বিবেচনা করুন

int factorial ( int input )
{
  int x, fact = 1;
  for ( x = input; x > 1; x--)
     fact *= x;
  return fact;
}

পুনরাবৃত্তি ফাংশন ব্যবহার করে এখন এটি বিবেচনা করুন

int factorial ( int input )
{
  if (input == 0)
  {
     return 1;
  }
  return input * factorial(input - 1);
}

এই দুটি পর্যবেক্ষণ করে, আমরা দেখতে পাচ্ছি যে পুনরাবৃত্তিগুলি সহজেই বোঝা যায়। তবে যদি এটি যত্ন সহ ব্যবহার না করা হয় তবে এটি ত্রুটি প্রবণতাও হতে পারে। মনে করুন আমরা যদি মিস না হয়ে যাই if (input == 0)তবে কোডটি কিছু সময়ের জন্য কার্যকর করা হবে এবং সাধারণত একটি স্ট্যাক ওভারফ্লো দিয়ে শেষ হবে।


6
আমি প্রকৃতপক্ষে পুনরাবৃত্ত সংস্করণটি বোঝার জন্য আরও সহজ পাই। আমি মনে করি প্রতিটি তার নিজের জন্য।
ম্যাক্সপাম

@ ম্যাক্সপিএম, একটি হাই অর্ডার রিকারসিভ সমাধান আরও ভাল: foldl (*) 1 [1..n]এটিই।
এসকে-যুক্তি

5

ক্যাচিংয়ের কারণে অনেক ক্ষেত্রে পুনরাবৃত্তি দ্রুত হয়, যা কর্মক্ষমতা উন্নত করে। উদাহরণস্বরূপ, এখানে traditionalতিহ্যবাহী মার্জ রুটিন ব্যবহার করে মার্জ সাজানোর পুনরাবৃত্ত সংস্করণ। ক্যাচিং উন্নত পারফরম্যান্সের কারণে এটি পুনরাবৃত্তির প্রয়োগের চেয়ে ধীর গতিতে চলবে।

Iterative বাস্তবায়ন

public static void sort(Comparable[] a)
{
    int N = a.length;
    aux = new Comparable[N];
    for (int sz = 1; sz < N; sz = sz+sz)
        for (int lo = 0; lo < N-sz; lo += sz+sz)
            merge(a, lo, lo+sz-1, Math.min(lo+sz+sz-1, N-1));
}

পুনরাবৃত্তিমূলক বাস্তবায়ন

private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi)
{
    if (hi <= lo) return;
    int mid = lo + (hi - lo) / 2;
    sort(a, aux, lo, mid);
    sort(a, aux, mid+1, hi);
    merge(a, aux, lo, mid, hi);
}

পিএস - অধ্যাপক কেভিন ওয়েইন (প্রিন্সটন বিশ্ববিদ্যালয়) কোর্সেরায় উপস্থাপিত অ্যালগরিদম কোর্সে এটি বলেছিলেন।


4

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


1
প্রকৃতপক্ষে, সংকলিত স্কালাল টেল-রিকার্সিভ ফাংশনটি বাইটোকোডের একটি লুপে সিদ্ধ করুন, যদি আপনি সেগুলিতে নজর রাখেন (প্রস্তাবিত)। কোনও ফাংশন কল ওভারহেড নেই। দ্বিতীয়ত, পুচ্ছ-পুনরাবৃত্তির ক্রিয়াকলাপগুলিতে পারস্পরিক পরিবর্তনশীল / পার্শ্ব প্রতিক্রিয়া বা স্পষ্টত লুপগুলির প্রয়োজন না হওয়ার সুবিধা রয়েছে, যা সঠিকতা প্রমাণ করা আরও সহজ করে তোলে।
বেন হার্ডি

4

পুনরাবৃত্তি এবং পুনরাবৃত্তি আপনি যে ব্যবসায়িক যুক্তি প্রয়োগ করতে চান তার উপর নির্ভর করে, যদিও বেশিরভাগ ক্ষেত্রে এটি আদান-প্রদানের সাথে ব্যবহার করা যেতে পারে। বেশিরভাগ বিকাশকারী পুনরাবৃত্তি করতে যান কারণ এটি বোঝা সহজ।


4

এটি ভাষার উপর নির্ভর করে। জাভাতে আপনার লুপগুলি ব্যবহার করা উচিত। কার্যকরী ভাষা পুনরাবৃত্তি অপ্টিমাইজ করে।


3

যদি আপনি কেবল একটি তালিকার উপরে পুনরাবৃত্তি করেন তবে নিশ্চিত হন, পুনরাবৃত্তি করুন।

অন্যান্য কয়েকটি উত্তর গাছের ট্র্যাভারসাল (গভীরতা-প্রথম) উল্লেখ করেছে। এটি সত্যিই এটির দুর্দান্ত উদাহরণ, কারণ খুব সাধারণ ডেটা স্ট্রাকচারের জন্য এটি করা খুব সাধারণ বিষয়। পুনরাবৃত্তি এই সমস্যার জন্য অত্যন্ত স্বজ্ঞাত।

এখানে "অনুসন্ধান করুন" পদ্ধতিগুলি দেখুন: http://penguin.ewu.edu/cscd300/Topic/BSTintro/index.html


3

পুনরাবৃত্তি একটি পুনরাবৃত্তির কোনও সম্ভাব্য সংজ্ঞার চেয়ে আরও সাধারণ (এবং এইভাবে - আরও মৌলিক)। আপনি কেবল একজোড়া সংযুক্তকারী (একটি হ্যাঁ, এমনকি একটি পুনরাবৃত্তি নিজেই যেমন একটি সিস্টেমে একটি অনুভূতি ধারণা) সহ একটি টুরিং-সম্পূর্ণ সিস্টেমটি সংজ্ঞায়িত করতে পারেন । ল্যাম্বদা ক্যালকুলাস একটি সমান শক্তিশালী মৌলিক ব্যবস্থা, যা পুনরাবৃত্ত ফাংশনগুলির বৈশিষ্ট্যযুক্ত। তবে আপনি যদি কোনও পুনরুক্তির সঠিকভাবে সংজ্ঞা দিতে চান তবে শুরু করতে আপনার আরও অনেক আদিম প্রয়োজন।

কোড হিসাবে - না, পুনরাবৃত্তির কোডটি খাঁটি পুনরাবৃত্তির চেয়ে বেশি বোঝা এবং বজায় রাখা সহজ, যেহেতু বেশিরভাগ ডেটা স্ট্রাকচার পুনরাবৃত্ত হয় rec অবশ্যই, এটি সঠিকভাবে পেতে একটি উচ্চতর অর্ডার ফাংশন এবং ক্লোজারগুলির সমর্থন সহ একটি ভাষার প্রয়োজন হবে, কমপক্ষে - সমস্ত স্ট্যান্ডার্ড সংযুক্তকারী এবং পুনরাবৃত্তিগুলি একটি ঝরঝরে উপায়ে পেতে। সি ++ এ অবশ্যই জটিল পুনরাবৃত্তির সমাধানগুলি কিছুটা কুৎসিত দেখাতে পারে, যদি না আপনি এফসি ++ এবং এর মতোই একজন হার্ড ব্যবহারকারী হন ।


পুনরাবৃত্তির কোডটি অনুসরণ করা অত্যন্ত কঠিন হতে পারে, বিশেষত যদি পরামিতিগুলির ক্রম পরিবর্তন হয় বা প্রতিটি পুনরাবৃত্তির সাথে প্রকারগুলি হয়। Iterative কোড খুব সহজ এবং বর্ণনামূলক হতে পারে। গুরুত্বপূর্ণ জিনিস হ'ল পাঠযোগ্যতার জন্য কোডিং (এবং তাই নির্ভরযোগ্যতা) প্রথমে পুনরাবৃত্তিযোগ্য বা পুনরাবৃত্তিযোগ্য কিনা, তবে প্রয়োজনে অনুকূলিত করুন।
মারকাস ক্লিমেটস

2

আমি মনে করব (নন লেজ) পুনরাবৃত্তিতে একটি নতুন স্ট্যাক ইত্যাদি বরাদ্দ করার জন্য পারফরম্যান্স হিট হবে যখনই ফাংশনটি বলা হবে (অবশ্যই ভাষার উপর নির্ভরশীল)।


2

এটি "পুনরাবৃত্তির গভীরতা" এর উপর নির্ভর করে। এটি ফাংশন কল ওভারহেড মোট কার্যকরকরণ সময়কে কতটা প্রভাবিত করবে তার উপর নির্ভর করে।

উদাহরণস্বরূপ, ক্লাসিক্যাল ফ্যাক্টরিয়ালটি পুনরাবৃত্ত পদ্ধতিতে গণনা করা খুব অকার্যকর কারণে: - ডেটা উপচে পড়ার ঝুঁকি - স্ট্যাক উপচে পড়া ঝুঁকি - ফাংশন কল ওভারহেড বাস্তবায়ন সময়ের 80% দখল করে

দাবা খেলায় অবস্থান বিশ্লেষণের জন্য ন্যূনতম সর্বাধিক অ্যালগরিদম বিকাশকালে যা পরবর্তী এন পদক্ষেপগুলি বিশ্লেষণ করে "বিশ্লেষণ গভীরতা" (যেমন আমি ^ _ ^ করছি) এর পুনরাবৃত্তিতে প্রয়োগ করা যেতে পারে


এখানে ugasoft এর সাথে সম্পূর্ণরূপে একমত ... এটি পুনরাবৃত্তির গভীরতার উপর নির্ভর করে .... এবং এর পুনরাবৃত্তি বাস্তবায়নের জটিলতার উপর ... আপনাকে উভয়ের তুলনা করতে হবে এবং কোনটি আরও কার্যকর তা দেখতে হবে ... এর মতো কোনও থাম্ব-রুল নেই। ..
রাজ্য বর্ধন

2

Recursion? আমি কোথায় শুরু করব, উইকি আপনাকে বলবে "এটি স্ব-অনুরূপ উপায়ে পুনরাবৃত্তি করার প্রক্রিয়া"

সেদিন ফিরে যখন আমি সি করছিলাম, সি ++ পুনরাবৃত্তি ছিল একটি godশ্বর প্রেরণ, "টেল রিকার্সন" এর মতো স্টাফ। আপনি অনেকগুলি বাছাই করা অ্যালগরিদম পুনরাবৃত্তি ব্যবহার করতে পারেন। দ্রুত সাজানোর উদাহরণ: http://alienryderflex.com/quicksort/

পুনরাবৃত্তি একটি নির্দিষ্ট সমস্যার জন্য দরকারী অন্যান্য অ্যালগরিদমের মতো। সম্ভবত আপনি সরাসরি বা প্রায়শই কোনও ব্যবহার না খুঁজে পেতে পারেন তবে সমস্যা হবে আপনি এটি খুশি হবেন।


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

ফেয়ার পয়েন্ট, এটি পিছনে ছিল। তবে আমি নিশ্চিত না যে এটি এখনও লেজ পুনরুক্তির জন্য প্রযোজ্য।
নিকজ

2

সি ++ এ যদি পুনরাবৃত্ত ফাংশনটি একটি স্বচ্ছন্দিত হয়, তবে সংকলকটির এটিকে আরও অনুকূল করার আরও সুযোগ রয়েছে, কারণ সমস্ত টাইপ ছাড় এবং ফাংশন ইনস্ট্যান্টেশনগুলি সংকলন সময়ে ঘটবে। আধুনিক সংকলকগুলি সম্ভব হলে ফাংশনটি ইনলাইন করতে পারে। সুতরাং কেউ যদি অপ্টিমাইজেশন পতাকা ব্যবহার করে -O3বা পছন্দ করে-O2 এর করে g++, তবে পুনরাবৃত্তিতে পুনরাবৃত্তির চেয়ে দ্রুত হওয়ার সুযোগ থাকতে পারে। পুনরুক্তিযোগ্য কোডগুলিতে, সংকলকটি এটির অনুকূলীকরণের জন্য কম সুযোগ পায়, কারণ এটি ইতিমধ্যে কম-বেশি অনুকূল অবস্থায় রয়েছে (যদি যথেষ্ট ভালভাবে লেখা থাকে)।

আমার ক্ষেত্রে, আমি পুনরাবৃত্ত এবং পুনরুক্তি উভয় উপায়ে আরমাদিলো ম্যাট্রিক্স অবজেক্টগুলি ব্যবহার করে স্কোয়ারিংয়ের মাধ্যমে ম্যাট্রিক্স এক্সপেনশনেশন প্রয়োগের চেষ্টা করছিলাম। অ্যালগরিদমটি এখানে পাওয়া যাবে ... https://en.wikedia.org/wiki/Exponentiation_by_squering । আমার ফাংশনগুলি টেম্পলেট করা হয়েছিল এবং আমি 1,000,000 12x12বিদ্যুতে উত্থিত ম্যাট্রিকগুলি গণনা করেছি 10। আমি নিম্নলিখিত ফলাফল পেয়েছি:

iterative + optimisation flag -O3 -> 2.79.. sec
recursive + optimisation flag -O3 -> 1.32.. sec

iterative + No-optimisation flag  -> 2.83.. sec
recursive + No-optimisation flag  -> 4.15.. sec

এই ফলাফলগুলি -std=c++11সিসি ++ ১১ পতাকা ( ) এর সাথে জিসিসি-৪.৮ এবং ইন্টেল এমকেএল সহ আর্মাদিলো .1.১ ব্যবহার করে প্রাপ্ত করা হয়েছে । ইন্টেল সংকলক এছাড়াও একই ফলাফল দেখায়।


1

মাইক ঠিক আছে। টেল পুনরাবৃত্তি জাভা সংকলক বা জেভিএম দ্বারা অনুকূলিত হয় না । আপনি সর্বদা এই জাতীয় কিছু দিয়ে একটি স্ট্যাক ওভারফ্লো পাবেন:

int count(int i) {
  return i >= 100000000 ? i : count(i+1);
}

3
আপনি স্কালায় না লিখলে ;-)
বেন হার্ডি

1

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


1

পুনরাবৃত্তির একটি অসুবিধা রয়েছে যে আপনি পুনরাবৃত্তি ব্যবহার করে যে অ্যালগরিদমটি লিখেন তাতে O (n) স্পেস জটিলতা রয়েছে। যদিও পুনরাবৃত্তিক শিকাগুলির ও (1) এর স্পেস জটিলতা রয়েছে rec এটি পুনরাবৃত্তির মাধ্যমে পুনরাবৃত্তিটি ব্যবহার করার সুবিধা। তাহলে আমরা কেন পুনরাবৃত্তি ব্যবহার করব?

নিচে দেখ.

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


1

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

উদাহরণস্বরূপ, কিছু ভাষায়, পুনরাবৃত্তাকার মাল্টিথ্রেডেড মার্জ সাজ্ট বাস্তবায়ন রয়েছে।

তবে আবার, মাল্টিথ্রেডিং পুনরাবৃত্তির পরিবর্তে লুপিংয়ের সাথে ব্যবহার করা যেতে পারে, সুতরাং এই সমন্বয়টি কতটা ভাল কাজ করবে তা ওএস এবং এর থ্রেড বরাদ্দকরণ প্রক্রিয়া সহ আরও বেশি কারণের উপর নির্ভর করে।


0

যতদূর আমি জানি, পার্ল লেজ-পুনরাবৃত্ত কলগুলি অনুকূল করে না, তবে আপনি এটি জাল করতে পারেন।

sub f{
  my($l,$r) = @_;

  if( $l >= $r ){
    return $l;
  } else {

    # return f( $l+1, $r );

    @_ = ( $l+1, $r );
    goto &f;

  }
}

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

মনে রাখবেন যে " my @_;" বা " local @_;" কোনও নেই, আপনি যদি এটি করেন তবে এটি আর কাজ করবে না।


0

কেবল Chrome 45.0.2454.85 মিটার ব্যবহার করে, পুনরাবৃত্তি খুব ভাল পরিমাণে দ্রুত বলে মনে হচ্ছে।

কোডটি এখানে:

(function recursionVsForLoop(global) {
    "use strict";

    // Perf test
    function perfTest() {}

    perfTest.prototype.do = function(ns, fn) {
        console.time(ns);
        fn();
        console.timeEnd(ns);
    };

    // Recursion method
    (function recur() {
        var count = 0;
        global.recurFn = function recurFn(fn, cycles) {
            fn();
            count = count + 1;
            if (count !== cycles) recurFn(fn, cycles);
        };
    })();

    // Looped method
    function loopFn(fn, cycles) {
        for (var i = 0; i < cycles; i++) {
            fn();
        }
    }

    // Tests
    var curTest = new perfTest(),
        testsToRun = 100;

    curTest.do('recursion', function() {
        recurFn(function() {
            console.log('a recur run.');
        }, testsToRun);
    });

    curTest.do('loop', function() {
        loopFn(function() {
            console.log('a loop run.');
        }, testsToRun);
    });

})(window);

ফলাফল

// 100 লুপের জন্য মান ব্যবহার করে রান

লুপ রান জন্য 100x। শেষ করার সময়: 7.683 মিমি

// 100 ফাংশনাল রিকার্সিভ অ্যাপ্রোচ ডাব্লু / লেজ পুনরাবৃত্তি ব্যবহার করে রান

100x পুনরাবৃত্তি রান। শেষ করার সময়: 4.841 মিমি

নীচের স্ক্রিনশটে, পুনরাবৃত্তি আবার বড় ব্যবধানে জয়ী হয় যখন পরীক্ষা প্রতি 300 চক্র চালানো হয়

পুনরাবৃত্তি আবার জিতল!


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

0

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

সংক্ষেপে: 1) পুনরুক্তি পোস্ট-অর্ডার ট্র্যাভারসাল সহজ নয় - যা ডিএফটি আরও জটিল করে তোলে 2) চক্রগুলি পুনরাবৃত্তি সহ চেক করা সহজ করে তোলে

বিবরণ:

পুনরাবৃত্তির ক্ষেত্রে, প্রাক এবং পোস্ট ট্র্যাভারসালগুলি তৈরি করা সহজ:

একটি দুর্দান্ত স্ট্যান্ডার্ড প্রশ্নটি কল্পনা করুন: "টাস্ক 5টি কার্যকর করার জন্য কার্যকর করা উচিত এমন সমস্ত কার্যগুলি মুদ্রণ করুন, যখন কার্যগুলি অন্যান্য কাজের উপর নির্ভর করে"

উদাহরণ:

    //key-task, value-list of tasks the key task depends on
    //"adjacency map":
    Map<Integer, List<Integer>> tasksMap = new HashMap<>();
    tasksMap.put(0, new ArrayList<>());
    tasksMap.put(1, new ArrayList<>());

    List<Integer> t2 = new ArrayList<>();
    t2.add(0);
    t2.add(1);
    tasksMap.put(2, t2);

    List<Integer> t3 = new ArrayList<>();
    t3.add(2);
    t3.add(10);
    tasksMap.put(3, t3);

    List<Integer> t4 = new ArrayList<>();
    t4.add(3);
    tasksMap.put(4, t4);

    List<Integer> t5 = new ArrayList<>();
    t5.add(3);
    tasksMap.put(5, t5);

    tasksMap.put(6, new ArrayList<>());
    tasksMap.put(7, new ArrayList<>());

    List<Integer> t8 = new ArrayList<>();
    t8.add(5);
    tasksMap.put(8, t8);

    List<Integer> t9 = new ArrayList<>();
    t9.add(4);
    tasksMap.put(9, t9);

    tasksMap.put(10, new ArrayList<>());

    //task to analyze:
    int task = 5;


    List<Integer> res11 = getTasksInOrderDftReqPostOrder(tasksMap, task);
    System.out.println(res11);**//note, no reverse required**

    List<Integer> res12 = getTasksInOrderDftReqPreOrder(tasksMap, task);
    Collections.reverse(res12);//note reverse!
    System.out.println(res12);

    private static List<Integer> getTasksInOrderDftReqPreOrder(Map<Integer, List<Integer>> tasksMap, int task) {
         List<Integer> result = new ArrayList<>();
         Set<Integer> visited = new HashSet<>();
         reqPreOrder(tasksMap,task,result, visited);
         return result;
    }

private static void reqPreOrder(Map<Integer, List<Integer>> tasksMap, int task, List<Integer> result, Set<Integer> visited) {

    if(!visited.contains(task)) {
        visited.add(task);
        result.add(task);//pre order!
        List<Integer> children = tasksMap.get(task);
        if (children != null && children.size() > 0) {
            for (Integer child : children) {
                reqPreOrder(tasksMap,child,result, visited);
            }
        }
    }
}

private static List<Integer> getTasksInOrderDftReqPostOrder(Map<Integer, List<Integer>> tasksMap, int task) {
    List<Integer> result = new ArrayList<>();
    Set<Integer> visited = new HashSet<>();
    reqPostOrder(tasksMap,task,result, visited);
    return result;
}

private static void reqPostOrder(Map<Integer, List<Integer>> tasksMap, int task, List<Integer> result, Set<Integer> visited) {
    if(!visited.contains(task)) {
        visited.add(task);
        List<Integer> children = tasksMap.get(task);
        if (children != null && children.size() > 0) {
            for (Integer child : children) {
                reqPostOrder(tasksMap,child,result, visited);
            }
        }
        result.add(task);//post order!
    }
}

দ্রষ্টব্য যে পুনরাবৃত্তির পোস্ট-অর্ডার-ট্র্যাভারসালটির পরবর্তী ফলাফলের বিপরীতের প্রয়োজন হয় না। শিশুরা প্রথম মুদ্রিত হয় এবং প্রশ্নটি আপনার টাস্কটি সর্বশেষে মুদ্রিত হয়। সবকিছু ঠিক আছে. আপনি একটি পুনরাবৃত্তিমূলক প্রাক-অর্ডার-ট্র্যাভারসাল করতে পারেন (উপরেও দেখানো হয়েছে) এবং এর জন্য ফলাফল তালিকার বিপরীতের প্রয়োজন হবে।

পুনরাবৃত্ত পদ্ধতির সাথে এত সহজ নয়! পুনরাবৃত্তির (একটি স্ট্যাক) পদ্ধতির ক্ষেত্রে আপনি কেবল প্রাক-অর্ডারিং-ট্র্যাভারসাল করতে পারেন, ফলে আপনি ফলাফলের অ্যারেটি বিপরীত করতে বাধ্য হয়েছেন:

    List<Integer> res1 = getTasksInOrderDftStack(tasksMap, task);
    Collections.reverse(res1);//note reverse!
    System.out.println(res1);

    private static List<Integer> getTasksInOrderDftStack(Map<Integer, List<Integer>> tasksMap, int task) {
    List<Integer> result = new ArrayList<>();
    Set<Integer> visited = new HashSet<>();
    Stack<Integer> st = new Stack<>();


    st.add(task);
    visited.add(task);

    while(!st.isEmpty()){
        Integer node = st.pop();
        List<Integer> children = tasksMap.get(node);
        result.add(node);
        if(children!=null && children.size() > 0){
            for(Integer child:children){
                if(!visited.contains(child)){
                    st.add(child);
                    visited.add(child);
                }
            }
        }
        //If you put it here - it does not matter - it is anyway a pre-order
        //result.add(node);
    }
    return result;
}

দেখতে সহজ, না?

তবে কিছু সাক্ষাত্কারে এটি একটি ফাঁদ।

এটির অর্থ নিম্নলিখিত: পুনরাবৃত্তির পদ্ধতির সাথে, আপনি গভীরতা ফার্স্ট ট্র্যাভারসাল বাস্তবায়ন করতে পারেন এবং তারপরে আপনার প্রাক বা পোস্টের কোন আদেশ দরকার তা নির্বাচন করতে পারেন (কেবল "মুদ্রণ" এর অবস্থান পরিবর্তন করে, "ফলাফলের তালিকায় যোগ করার ক্ষেত্রে" আমাদের ক্ষেত্রে )। পুনরাবৃত্তির (একটি স্ট্যাক) পদ্ধতির সাহায্যে আপনি সহজেই কেবল প্রাক-অর্ডার ট্রভারসাল করতে পারেন এবং তাই যখন বাচ্চাদের প্রথমে মুদ্রণ করা প্রয়োজন (বেশিরভাগ পরিস্থিতি যখন আপনার নীচের নোডগুলি থেকে প্রিন্ট শুরু করতে হবে, উপরের দিকে যেতে হবে) - আপনি আছেন বিপদের. আপনার যদি সমস্যা হয় তবে আপনি পরে বিপরীত হতে পারেন, তবে এটি আপনার অ্যালগরিদমের সাথে যুক্ত হবে। এবং যদি কোনও সাক্ষাত্কারকারী তার ঘড়ির দিকে তাকিয়ে থাকে তবে এটি আপনার পক্ষে সমস্যা হতে পারে। পুনরাবৃত্ত পোস্ট-অর্ডার ট্র্যাভারসাল করার জটিল উপায় রয়েছে, সেগুলি বিদ্যমান, তবে এগুলি সহজ নয় । উদাহরণ:https://www.geeksforgeeks.org/iterative-postorder-traversal-using-stack/

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

আমি পুনরাবৃত্তি ব্যবহার করব এবং তারপরে বলব: "ঠিক আছে, তবে পুনরাবৃত্তি আমাকে ব্যবহৃত স্মৃতিতে আরও সরাসরি নিয়ন্ত্রণ সরবরাহ করতে পারে, আমি স্ট্যাকের আকারটি সহজেই পরিমাপ করতে পারি এবং কিছু বিপজ্জনক ওভারফ্লো বর্জন করতে পারি .."

পুনরাবৃত্তির আরও একটি প্লাস - কোনও গ্রাফের চক্র এড়ানো / লক্ষ্য করা সহজ।

উদাহরণ (প্রিউডোকোড):

dft(n){
    mark(n)
    for(child: n.children){
        if(marked(child)) 
            explode - cycle found!!!
        dft(child)
    }
    unmark(n)
}

0

এটি পুনরাবৃত্তি হিসাবে বা অনুশীলন হিসাবে লিখতে মজাদার হতে পারে।

তবে কোডটি যদি উত্পাদনে ব্যবহার করতে হয় তবে আপনার স্ট্যাকের ওভারফ্লো হওয়ার সম্ভাবনা বিবেচনা করা উচিত।

টেল রিকার্সন অপ্টিমাইজেশন স্ট্যাক ওভারফ্লো কেটে ফেলতে পারে, তবে আপনি কি এটি তৈরির সমস্যার মধ্য দিয়ে যেতে চান এবং আপনার পরিবেশের মধ্যে এটি অপ্টিমাইজেশান রয়েছে কিনা তা আপনার জানা উচিত।

প্রতিবার অ্যালগরিদম পুনরাবৃত্তি হয়, তথ্যের আকার কত বা nকমিয়ে দেওয়া হয়?

আপনি যদি nপ্রতিবার পুনরাবৃত্তি করেন তবে ডেটার আকার বা অর্ধেক কমিয়ে দিচ্ছেন , তবে সাধারণভাবে আপনাকে স্ট্যাকের ওভারফ্লো সম্পর্কে উদ্বিগ্ন হওয়ার দরকার নেই। বলুন, প্রোগ্রামটি ওভারফ্লো স্ট্যাক করার জন্য যদি এটি 4,000 স্তর গভীর বা 10,000 স্তর গভীর হওয়া প্রয়োজন তবে আপনার প্রোগ্রামের ওভারফ্লো স্ট্যাক করার জন্য আপনার ডেটা আকারটি প্রায় 4000 ডলার হওয়া দরকার। এটিকে পরিপ্রেক্ষিতে রাখতে, একটি বৃহত্তম স্টোরেজ ডিভাইসটি সম্প্রতি 2 61 বাইট ধারণ করতে পারে এবং যদি আপনার কাছে এই জাতীয় ডিভাইসগুলির মধ্যে 2 61 থাকে , আপনি কেবলমাত্র 122 ডেটা আকার নিয়ে কাজ করছেন। আপনি যদি মহাবিশ্বের সমস্ত পরমাণুর দিকে নজর রাখেন তবে অনুমান করা হয় এটি 2 এরও কম হতে পারে 84। 14 বিলিয়ন বছর আগে মহাবিশ্বের জন্মের অনুমানের পরে আপনার যদি প্রতি মিলি সেকেন্ডের জন্য মহাবিশ্বের সমস্ত তথ্য এবং তাদের রাজ্যগুলির সাথে ডিল করার প্রয়োজন হয় তবে এটি কেবল 153 ডলার হতে পারে । সুতরাং যদি আপনার প্রোগ্রামটি 4000 ইউনিট ডেটা nপরিচালনা করতে পারে বা আপনি মহাবিশ্বের সমস্ত ডেটা পরিচালনা করতে পারেন এবং প্রোগ্রামটি ওভারফ্লোতে স্ট্যাক করবে না। যদি আপনার 4000 ডলার (4000-বিট পূর্ণসংখ্যার) এর চেয়ে বড় সংখ্যার সাথে ডিল করার প্রয়োজন না হয় তবে সাধারণভাবে আপনাকে স্ট্যাক ওভারফ্লো সম্পর্কে চিন্তা করার দরকার নেই।

যাইহোক, যদি আপনি ডাটা বা আকার হ্রাস nকরার প্রত্যেক সময়ে recurse একটি ধ্রুবক পরিমাণ দ্বারা, তাহলে আপনি স্ট্যাক ওভারফ্লো মধ্যে যখন আপনার প্রোগ্রাম ভাল চালায় যখন রান করতে পারেন nহয় 1000কিন্তু কিছু পরিস্থিতিতে, যখন nনিছক হয়ে 20000

সুতরাং আপনার যদি স্ট্যাক ওভারফ্লো হওয়ার সম্ভাবনা থাকে তবে এটিকে পুনরাবৃত্তি সমাধান করার চেষ্টা করুন।


-1

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

আমরা একটি সাধারণ গাছের জন্য একটি প্রকারের পরিচয় করিয়ে দিই:

data Tree a = Branch (Tree a) (Tree a)
            | Leaf a
            deriving (Eq)

"এই গাছটি একটি শাখা (যা দুটি গাছ ধারণ করে) বা একটি পাতা (যাতে একটি ডেটা মান থাকে) বলে আমরা এই সংজ্ঞাটি পড়তে পারি।" সুতরাং পাতার ন্যূনতম কেস এক ধরণের। যদি গাছ একটি পাতা না হয় তবে এটি অবশ্যই দুটি গাছযুক্ত যৌগিক গাছ হবে। এগুলি একমাত্র ঘটনা।

একটি গাছ তৈরি করা যাক:

example :: Tree Int
example = Branch (Leaf 1) 
                 (Branch (Leaf 2) 
                         (Leaf 3))

এখন, ধরুন আমরা গাছের প্রতিটি মানের সাথে 1 যুক্ত করতে চাই। আমরা কল করে এটি করতে পারি:

addOne :: Tree Int -> Tree Int
addOne (Branch a b) = Branch (addOne a) (addOne b)
addOne (Leaf a)     = Leaf (a + 1)

প্রথম, লক্ষ্য করুন যে এটি আসলে একটি পুনরাবৃত্ত সংজ্ঞা। এটি ডেটা কনস্ট্রাক্টর শাখা এবং লিফকে কেস হিসাবে গ্রহণ করে (এবং যেহেতু লিফ ন্যূনতম এবং এগুলি কেবলমাত্র সম্ভাব্য কেস) তাই আমরা নিশ্চিত যে ফাংশনটি সমাপ্ত হবে।

পুনরাবৃত্ত শৈলীতে অ্যাডঅন লিখতে কী লাগবে? স্বেচ্ছাসেবী সংখ্যার শাখাগুলিতে লুপিংয়ের মতো দেখতে কেমন হবে?

এছাড়াও, এই ধরণের পুনরাবৃত্তিটি প্রায়শই "ফান্টেক্টর" এর শর্তে সন্ধান করা যেতে পারে। আমরা সংজ্ঞা দিয়ে গাছগুলিকে ফ্যাক্টরগুলিতে তৈরি করতে পারি:

instance Functor Tree where fmap f (Leaf a)     = Leaf (f a)
                            fmap f (Branch a b) = Branch (fmap f a) (fmap f b)

এবং সংজ্ঞায়িত:

addOne' = fmap (+1)

আমরা অন্যান্য পুনরাবৃত্তির স্কিমগুলি তৈরি করতে পারি, যেমন একটি বীজগণিত ডেটা ধরণের জন্য ক্যাটামোর্ফিজম (বা ভাঁজ)। ছদ্মবেশ ব্যবহার করে আমরা লিখতে পারি:

addOne'' = cata go where
           go (Leaf a) = Leaf (a + 1)
           go (Branch a b) = Branch a b

-2

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

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

উচ্চ স্তরের ভাষা এবং এমনকি ঝনঝন / সিপিপি এটি পটভূমিতে একই প্রয়োগ করতে পারে।


1
"স্ট্যাক ওভারফ্লো কেবল তখনই ঘটতে পারে যখন আপনি এমন ভাষায় প্রোগ্রামিং করেন যা বিল্ট মেমোরি ম্যানেজমেন্টে নেই" - এর কোনও মানে নেই। বেশিরভাগ ভাষাগুলি সীমিত আকারের স্ট্যাক ব্যবহার করে, তাই পুনরাবৃত্তি খুব শীঘ্রই একটি ব্যর্থতার দিকে নিয়ে যাবে।
স্ট্যাসিগার্ল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.