सबसे पहले, सूची एक प्रकार के पेड़ हैं। यदि हम किसी सूची को एक लिंक्ड सूची के रूप में दर्शाते हैं , तो यह सिर्फ एक पेड़ है जिसके प्रत्येक नोड में 1 या 0 वंशज हैं।
पार्स ट्री केवल डेटा संरचना के रूप में पेड़ों का उपयोग है। कंप्यूटर विज्ञान में पेड़ों के कई अनुप्रयोग हैं, जिनमें छंटाई, नक्शे को लागू करना, साहचर्य सरणियाँ आदि शामिल हैं।
सामान्य तौर पर, सूची, पेड़ आदि पुनरावर्ती डेटा संरचनाएं हैं: प्रत्येक नोड में कुछ जानकारी और समान डेटा संरचना का एक और उदाहरण होता है। तह ऐसे सभी संरचनाओं पर एक ऑपरेशन है जो पुनरावर्ती रूप से नोड्स को "नीचे ऊपर" मानों में बदल देता है। अनफॉल्डिंग रिवर्स प्रक्रिया है, यह मानों को "टॉप डाउन" नोड में परिवर्तित करता है।
किसी दिए गए डेटा संरचना के लिए, हम यंत्रवत् उनके तह और खुलासा कार्यों का निर्माण कर सकते हैं।
एक उदाहरण के रूप में, चलो सूची लेते हैं। (मैं इसे टाइप किया गया उदाहरण के लिए हास्केल का उपयोग करूंगा और इसका सिंटैक्स बहुत साफ है।) सूची या तो एक अंत या एक मूल्य और एक "पूंछ" है।
data List a = Nil | Cons a (List a)
अब कल्पना करते हैं कि हम एक सूची को मोड़ रहे हैं। प्रत्येक चरण में, हमारे पास वर्तमान नोड को मोड़ना है और हमने पहले ही इसके पुनरावर्ती उप-नोड को मोड़ दिया है। हम इस राज्य का प्रतिनिधित्व कर सकते हैं
data ListF a r = NilF | ConsF a r
जहाँ rइंटरलेट वैल्यू का निर्माण सबलिस्ट को फोल्ड करके किया जाता है। यह हमें सूची पर एक तह समारोह व्यक्त करने की अनुमति देता है:
foldList :: (ListF a r -> r) -> List a -> r
foldList f Nil = f NilF
foldList f (Cons x xs) = f (ConsF x (foldList f xs))
हम इसकी सब लिटर पर पुनरावर्ती रूप से मोड़कर परिवर्तित Listकरते हैं ListFऔर फिर परिभाषित फ़ंक्शन का उपयोग करते हैं ListF। यदि आप इसके बारे में सोचते हैं, तो यह मानक का एक और प्रतिनिधित्व है foldr:
foldr :: (a -> r -> r) -> r -> List a -> r
foldr f z = foldList g
where
g NilF = z
g (ConsF x r) = f x r
हम unfoldListएक ही फैशन में निर्माण कर सकते हैं :
unfoldList :: (r -> ListF a r) -> r -> List a
unfoldList f r = case f r of
NilF -> Nil
ConsF x r' -> Cons x (unfoldList f r')
फिर, यह सिर्फ एक और प्रतिनिधित्व है unfoldr:
unfoldr :: (r -> Maybe (a, r)) -> r -> [a]
(ध्यान दें कि Maybe (a, r)यह आइसोमॉर्फिक है ListF a r।)
और हम वनों की कटाई का भी निर्माण कर सकते हैं:
deforest :: (ListF a r -> r) -> (s -> ListF a s) -> s -> r
deforest f u s = f (map (deforest f u) (u s))
where
map h NilF = NilF
map h (ConsF x r) = ConsF x (h r)
यह केवल मध्यवर्ती को छोड़ देता है Listऔर फोल्डिंग और अनफॉल्डिंग फ़ंक्शन को एक साथ फ़्यूज़ करता है।
यही प्रक्रिया किसी भी पुनरावर्ती डेटा संरचना पर लागू की जा सकती है। उदाहरण के लिए, एक पेड़ जिसके नोड्स में 0, 1, 2 हो सकते हैं या 1- या 0-ब्रांचिंग नोड्स के मूल्यों के साथ वंशज हो सकते हैं:
data Tree a = Bin (Tree a) (Tree a) | Un a (Tree a) | Leaf a
data TreeF a r = BinF r r | UnF a r | LeafF a
treeFold :: (TreeF a r -> r) -> Tree a -> r
treeFold f (Leaf x) = f (LeafF x)
treeFold f (Un x r) = f (UnF x (treeFold f r))
treeFold f (Bin r1 r2) = f (BinF (treeFold f r1) (treeFold f r2))
treeUnfold :: (r -> TreeF a r) -> r -> Tree a
treeUnfold f r = case f r of
LeafF x -> Leaf x
UnF x r -> Un x (treeUnfold f r)
BinF r1 r2 -> Bin (treeUnfold f r1) (treeUnfold f r2)
बेशक, हम deforestTreeपहले की तरह यंत्रवत रूप से बना सकते हैं ।
(आमतौर पर, हम treeFoldअधिक सुविधाजनक रूप में व्यक्त करेंगे:
treeFold' :: (r -> r -> r) -> (a -> r -> r) -> (a -> r) -> Tree a -> r
)
मैं विवरण छोड़ दूँगा, मुझे आशा है कि पैटर्न स्पष्ट है।
यह सभी देखें: