আপনি পাঁচটি ফুলযুক্ত একটি দানিটি কীভাবে খালি করবেন?
উত্তর: ফুলদানিটি খালি না থাকলে আপনি একটি ফুল বের করেন এবং তারপরে আপনি চারটি ফুলযুক্ত একটি ফুলদানি খালি করুন।
আপনি কীভাবে চারটি ফুলযুক্ত একটি ফুলদানি খালি করবেন?
উত্তর: ফুলদানিটি খালি না থাকলে আপনি একটি ফুল বের করেন এবং তারপরে আপনি তিনটি ফুলযুক্ত একটি ফুলদানি খালি করুন।
তিনটি ফুল সম্বলিত ফুলদানিটি কীভাবে খালি করবেন?
উত্তর: ফুলদানিটি খালি না থাকলে আপনি একটি ফুল বের করেন এবং তারপরে আপনি দুটি ফুলযুক্ত একটি ফুলদানি খালি করুন।
আপনি দুটি ফুলযুক্ত একটি দানিটি কীভাবে খালি করবেন?
উত্তর: ফুলদানিটি খালি না হলে আপনি একটি ফুল বের করেন এবং তারপরে আপনি একটি ফুলের একটি দানি খালি করেন।
আপনি কীভাবে একটি ফুলের ফুলদানি খালি করবেন?
উত্তর: ফুলদানিটি খালি না থাকলে আপনি একটি ফুল বের করেন এবং তারপরে কোনও ফুল নেই এমন ফুলদানি খালি করুন।
ফুল নেই এমন ফুলদানিটি কীভাবে খালি করবেন?
উত্তর: ফুলদানিটি খালি না থাকলে আপনি একটি ফুল বের করেন তবে ফুলদানি খালি তাই আপনার কাজ শেষ।
এটা পুনরাবৃত্তি। আসুন এটি সাধারণীকরণ করুন:
কীভাবে আপনি এন সহ একটি দানি খালি করবেন ?
উত্তর: যদি ফুলদানিটি খালি না থাকে তবে আপনি একটি ফুল বের করেন এবং তারপরে আপনি এন -1যুক্ত একটি ফুলদানি খালি করুন ।
হুম, আমরা কি কোডটিতে দেখতে পারি?
void emptyVase( int flowersInVase ) {
if( flowersInVase > 0 ) {
// take one flower and
emptyVase( flowersInVase - 1 ) ;
} else {
// the vase is empty, nothing to do
}
}
হুম, আমরা কি কেবল লুপের জন্য এটি করতে পারি না?
কেন, হ্যাঁ, পুনরাবৃত্তি পুনরাবৃত্তির সাথে প্রতিস্থাপন করা যেতে পারে, তবে প্রায়শই পুনরাবৃত্তি আরও মার্জিত হয়।
গাছ সম্পর্কে কথা বলা যাক। কম্পিউটার বিজ্ঞানে, একটি গাছ নোড দ্বারা গঠিত একটি কাঠামো , যেখানে প্রতিটি নোডে এমন কিছু বাচ্চা থাকে যা নোড বা নালও হয়। একটি বাইনারি ট্রি হ'ল নোড দিয়ে তৈরি এমন গাছ যা ঠিক দুটি বাচ্চা থাকে, সাধারণত "বাম" এবং "ডান" বলে; আবার বাচ্চারা নোড বা নাল হতে পারে। একটি মূল একটি নোড যে অন্য কোন নোড সন্তান নয়।
কল্পনা করুন যে একটি নোড, তার শিশুদের পাশাপাশি, একটি মান, একটি সংখ্যা আছে এবং কল্পনা করুন যে আমরা কিছু গাছের সমস্ত মান যোগ করতে চাই।
যে কোনও একটি নোডের মান যোগ করতে, আমরা নোডের মানটি তার বাম সন্তানের মান, যদি কোনও হয় এবং তার ডান সন্তানের মান, যদি কোনও যোগ করে দেব। এখন মনে রাখবেন যে বাচ্চারা, যদি তারা শূন্য না হয় তবে তারা নোডও।
বাম সন্তানের যোগফলের জন্য, আমরা চাইল্ড নোডের মানটি তার বাম সন্তানের মান, যদি কোনও হয় এবং তার ডান সন্তানের মান, যদি কোনও যোগ করে দেব।
সুতরাং বাম সন্তানের বাম সন্তানের মানটি যোগ করতে, আমরা চাইল্ড নোডের মানটি তার বাম সন্তানের মান, যদি কোনও হয় এবং তার ডান সন্তানের মান, যদি কোনও যোগ করে দেব।
সম্ভবত আপনি অনুমান করেছেন যে আমি এই সাথে কোথায় যাচ্ছি, এবং কিছু কোড দেখতে চান? ঠিক আছে:
struct node {
node* left;
node* right;
int value;
} ;
int sumNode( node* root ) {
// if there is no tree, its sum is zero
if( root == null ) {
return 0 ;
} else { // there is a tree
return root->value + sumNode( root->left ) + sumNode( root->right ) ;
}
}
লক্ষ্য করুন যে বাচ্চারা নাল বা নোডগুলি রয়েছে কিনা তা স্পষ্টভাবে পরীক্ষা করার পরিবর্তে, আমরা কেবল নাল নোডের জন্য পুনরাবৃত্ত ফাংশনটি শূন্য করে ফেলি।
সুতরাং বলুন আমাদের কাছে এমন একটি গাছ রয়েছে যা দেখতে দেখতে (সংখ্যাগুলি মানগুলি হয়, স্ল্যাশগুলি শিশুদের দিকে নির্দেশ করে এবং @ এর অর্থ পয়েন্টারটি নালার দিকে নির্দেশ করে):
5
/ \
4 3
/\ /\
2 1 @ @
/\ /\
@@ @@
আমরা যদি রুটটিতে SumNode কল করি (মান 5 সহ নোড), আমরা ফিরে আসব:
return root->value + sumNode( root->left ) + sumNode( root->right ) ;
return 5 + sumNode( node-with-value-4 ) + sumNode( node-with-value-3 ) ;
এটি জায়গায় প্রসারিত করা যাক। আমরা যেখানেই SumNode দেখতে পাচ্ছি, আমরা এটিকে রিটার্নের স্টেটমেন্টের প্রসারণের সাথে প্রতিস্থাপন করব:
sumNode( node-with-value-5);
return root->value + sumNode( root->left ) + sumNode( root->right ) ;
return 5 + sumNode( node-with-value-4 ) + sumNode( node-with-value-3 ) ;
return 5 + 4 + sumNode( node-with-value-2 ) + sumNode( node-with-value-1 )
+ sumNode( node-with-value-3 ) ;
return 5 + 4
+ 2 + sumNode(null ) + sumNode( null )
+ sumNode( node-with-value-1 )
+ sumNode( node-with-value-3 ) ;
return 5 + 4
+ 2 + 0 + 0
+ sumNode( node-with-value-1 )
+ sumNode( node-with-value-3 ) ;
return 5 + 4
+ 2 + 0 + 0
+ 1 + sumNode(null ) + sumNode( null )
+ sumNode( node-with-value-3 ) ;
return 5 + 4
+ 2 + 0 + 0
+ 1 + 0 + 0
+ sumNode( node-with-value-3 ) ;
return 5 + 4
+ 2 + 0 + 0
+ 1 + 0 + 0
+ 3 + sumNode(null ) + sumNode( null ) ;
return 5 + 4
+ 2 + 0 + 0
+ 1 + 0 + 0
+ 3 + 0 + 0 ;
return 5 + 4
+ 2 + 0 + 0
+ 1 + 0 + 0
+ 3 ;
return 5 + 4
+ 2 + 0 + 0
+ 1
+ 3 ;
return 5 + 4
+ 2
+ 1
+ 3 ;
return 5 + 4
+ 3
+ 3 ;
return 5 + 7
+ 3 ;
return 5 + 10 ;
return 15 ;
এখন দেখুন কীভাবে আমরা সম্মিলিত গভীরতার একটি কাঠামো এবং "শাখাবদ্ধতা" জয় করেছিলাম, এটি একটি যৌগিক টেমপ্লেটের পুনরাবৃত্তি হিসাবে বিবেচনা করে? প্রতিবার আমাদের SumNode ফাংশনটির মাধ্যমে, আমরা কেবলমাত্র একটি একক নোডের সাথে ডিল করেছি, যদি একটি / তারপরে শাখা ব্যবহার করি, এবং দুটি সাধারণ রিটার্ন স্টেটমেন্ট যা প্রায় তাদের থ্রিজগুলি লিখেছিল, সরাসরি আমাদের স্পেসিফিকেশন থেকে?
How to sum a node:
If a node is null
its sum is zero
otherwise
its sum is its value
plus the sum of its left child node
plus the sum of its right child node
এটা পুনরাবৃত্তি শক্তি।
উপরের ফুলদানির উদাহরণটি পুচ্ছ পুনরাবৃত্তির একটি উদাহরণ । সমস্ত লেজ পুনরাবৃত্তি অর্থ হ'ল পুনরাবৃত্ত ফাংশনে, যদি আমরা পুনরাবৃত্তি করি (এটি যদি আমরা ফাংশনটিকে আবারও ডাকি), এটি ছিল আমাদের শেষ কাজ।
গাছের উদাহরণটি লেজ পুনরাবৃত্তিযোগ্য ছিল না, কারণ যদিও আমরা শেষ কাজটি করেছি ডান সন্তানের পুনরাবৃত্তি করা, আমরা বাম সন্তানের পুনরাবৃত্তি করার আগে।
প্রকৃতপক্ষে, আমরা ক্রমগুলিকে বাচ্চাদের ডেকে বলেছি এবং বর্তমান নোডের মানটি মোটেও কিছু যায় আসে না, কারণ সংযোজনটি পরিবর্তনীয়।
এখন একটি অপারেশন তাকান যেখানে অর্ডার বিষয়টি বিবেচনা করে। আমরা নোডের একটি বাইনারি গাছ ব্যবহার করব, তবে এবার অনুষ্ঠিত মানটি একটি সংখ্যা নয়, একটি অক্ষর হবে।
আমাদের গাছ যে কোনো নোড জন্য, তার চরিত্র আসে একটি বিশেষ সম্পত্তি হবে পরে চরিত্র তার বাম সন্তানের দ্বারা এবং অনুষ্ঠিত (ক্রম অনুযায়ী) সামনে (ক্রম অনুযায়ী) অক্ষর এর ডান সন্তান দ্বারা অনুষ্ঠিত।
আমরা যা করতে চাই তা হ'ল গাছটিকে বর্ণানুক্রমিক ক্রমে মুদ্রণ করা। গাছটি বিশেষ সম্পত্তি দেওয়া, এটি করা সহজ। আমরা কেবল বাম শিশুটি, তারপরে নোডের চরিত্রটি, তারপরে ডান শিশুটি প্রিন্ট করব।
আমরা কেবল উইলি-নিলি মুদ্রণ করতে চাই না, তাই আমরা আমাদের ফাংশনটি মুদ্রণের জন্য পাস করব। এটি মুদ্রণ (চর) ফাংশন সহ একটি অবজেক্ট হবে; এটি কীভাবে কাজ করে সে সম্পর্কে আমাদের চিন্তা করার দরকার নেই, যখন প্রিন্ট বলা হয় তখন এটি কোনও কোনও জায়গায় প্রিন্ট করবে।
কোডে এটি দেখতে দিন:
struct node {
node* left;
node* right;
char value;
} ;
// don't worry about this code
class Printer {
private ostream& out;
Printer( ostream& o ) :out(o) {}
void print( char c ) { out << c; }
}
// worry about this code
int printNode( node* root, Printer& printer ) {
// if there is no tree, do nothing
if( root == null ) {
return ;
} else { // there is a tree
printNode( root->left, printer );
printer.print( value );
printNode( root->right, printer );
}
Printer printer( std::cout ) ;
node* root = makeTree() ; // this function returns a tree, somehow
printNode( root, printer );
ক্রিয়াকলাপের বিষয়টিকে এখন বিবেচনা করার পাশাপাশি, এই উদাহরণটি চিত্রিত করে যে আমরা জিনিসগুলিকে পুনরাবৃত্ত ফাংশনে স্থান দিতে পারি। কেবলমাত্র আমাদের যা করতে হবে তা হ'ল প্রতিটি রিকার্সিভ কলটিতে আমরা এটি পাশাপাশি চালিয়ে যাচ্ছি তা নিশ্চিত করা। আমরা ফাংশনে একটি নোড পয়েন্টার এবং একটি প্রিন্টারে পাস করেছি এবং প্রতিটি পুনরাবৃত্ত কলটিতে আমরা তাদের "ডাউন" দিয়েছি।
এখন যদি আমাদের গাছটি দেখতে এমন হয়:
k
/ \
h n
/\ /\
a j @ @
/\ /\
@@ i@
/\
@@
আমরা কী ছাপব?
From k, we go left to
h, where we go left to
a, where we go left to
null, where we do nothing and so
we return to a, where we print 'a' and then go right to
null, where we do nothing and so
we return to a and are done, so
we return to h, where we print 'h' and then go right to
j, where we go left to
i, where we go left to
null, where we do nothing and so
we return to i, where we print 'i' and then go right to
null, where we do nothing and so
we return to i and are done, so
we return to j, where we print 'j' and then go right to
null, where we do nothing and so
we return to j and are done, so
we return to h and are done, so
we return to k, where we print 'k' and then go right to
n where we go left to
null, where we do nothing and so
we return to n, where we print 'n' and then go right to
null, where we do nothing and so
we return to n and are done, so
we return to k and are done, so we return to the caller
সুতরাং আমরা যদি কেবল লাইনগুলি দেখি তবে আমরা কী ছাপলাম:
we return to a, where we print 'a' and then go right to
we return to h, where we print 'h' and then go right to
we return to i, where we print 'i' and then go right to
we return to j, where we print 'j' and then go right to
we return to k, where we print 'k' and then go right to
we return to n, where we print 'n' and then go right to
আমরা দেখতে পেয়েছি যে আমরা "অহিজন" মুদ্রিত করেছি, যা প্রকৃতপক্ষে বর্ণানুক্রমিক ক্রমে রয়েছে।
বর্ণানুক্রমিক ক্রমে একটি নোড কীভাবে প্রিন্ট করতে হয় তা জেনে আমরা বর্ণমালা অনুসারে একটি সম্পূর্ণ গাছ মুদ্রণ পরিচালনা করি manage যা ঠিক ছিল (কারণ আমাদের গাছে বর্ণের পরে বর্ণের বামে মানগুলি অর্ডার করার বিশেষ সম্পত্তি ছিল) নোডের মান মুদ্রণের আগে বাম সন্তানের মুদ্রণ করা এবং নোডের মান মুদ্রণের পরে ডান সন্তানের মুদ্রণ করা জেনে ছিল।
আর যে পুনরাবৃত্তির শক্তি: শুধুমাত্র কিভাবে পুরো একটি অংশ করতে বুদ্ধিমান (এবং যখন recursing থামাতে বুদ্ধিমান) দ্বারা পুরো জিনিস করতে সক্ষম হচ্ছে।
এটি বেশিরভাগ ভাষায় স্মরণ করে অপারেটর || ("বা") শর্ট সার্কিট যখন এর প্রথম অপারেন্ডটি সত্য হয়, তখন সাধারণ পুনরাবৃত্তির কাজটি হয়:
void recurse() { doWeStop() || recurse(); }
লুক এম মন্তব্য করেছেন:
এই জাতীয় উত্তরের জন্য একটি ব্যাজ তৈরি করা উচিত। অভিনন্দন!
ধন্যবাদ, লুক! তবে, আসলে, কারণ আমি এই উত্তরটি চারবারের বেশি সম্পাদনা করেছি (শেষ উদাহরণটি যুক্ত করতে, তবে বেশিরভাগ ক্ষেত্রে টাইপগুলি সংশোধন করতে এবং এটি পোলিশ করতে - একটি ক্ষুদ্র নেটবুক কীবোর্ডে টাইপ করা কঠিন), এর জন্য আমি আর কোনও পয়েন্ট পেতে পারি না । যা কিছুটা ভবিষ্যতের উত্তরগুলিতে যথাসাধ্য চেষ্টা করা থেকে নিরুৎসাহিত করে।
এখানে আমার মন্তব্য দেখুন: /programming/128434/ কি-are-commune-wiki-posts-in-stackoverflow / 718699#718699