বিআইটি: বাইনারি সূচকযুক্ত গাছের পিছনে অন্তর্নিহিততা কী এবং কীভাবে এটি সম্পর্কে ভাবা হয়েছিল?


99

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


4
উইকিপিডিয়ায় একটি নিবন্ধ দাবি করেছে যে এগুলিকে ফেনউইক ট্রি বলা হয় ।
ডেভিড হার্কনেস

2
@ ডেভিডহার্কনেস- পিটার ফেনউইক ডেটা স্ট্রাকচার আবিষ্কার করেছেন, তাই তাদের মাঝে মাঝে ফেনউইক ট্রি বলা হয়। তার মূল কাগজে ( citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.8917 এ পাওয়া যায় ), সেগুলিকে বাইনারি সূচকযুক্ত গাছ হিসাবে উল্লেখ করেছে। দুটি শব্দটি প্রায়শই পরস্পরের পরিবর্তে ব্যবহৃত হয়।
টেম্পলেটটিফাইফ

1
নিম্নলিখিত উত্তরটি বাইনারি সূচকযুক্ত গাছগুলির একটি খুব সুন্দর "ভিজ্যুয়াল" অন্তর্দৃষ্টি জানায় cs.stackexchange.com/questions/42811/…
রবিহ কোডেহ

1
আমি জানি আপনি কেমন অনুভব করছেন, প্রথমবার যখন আমি টপকোডার নিবন্ধটি পড়েছিলাম তখন মনে হয়েছিল কেবল যাদু।
রকস্টার

উত্তর:


168

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

ধরা যাক, উদাহরণস্বরূপ, আপনি মোট 7 টি বিভিন্ন উপাদানের জন্য ক্রমসংক্রান্ত ফ্রিকোয়েন্সি সঞ্চয় করতে চান। আপনি সাতটি বালতি লিখে নম্বরটি বিতরণ করা শুরু করতে পারেন:

[   ] [   ] [   ] [   ] [   ] [   ] [   ]
  1     2     3     4     5     6     7

এখন, ধরুন যে ক্রমবর্ধমান ফ্রিকোয়েন্সিগুলি এরকম কিছু দেখায়:

[ 5 ] [ 6 ] [14 ] [25 ] [77 ] [105] [105]
  1     2     3     4     5     6     7

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

[ 5 ] [ 6 ] [21 ] [32 ] [84 ] [112] [112]
  1     2     3     4     5     6     7

এটির সাথে সমস্যাটি হ'ল এটি করতে ও (এন) সময় লাগে যা এন বড় হলে বেশ ধীর হয়।

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

Before:
[ 5 ] [ 6 ] [21 ] [32 ] [84 ] [112] [112]
  1     2     3     4     5     6     7

After:
[ +5] [ +1] [+15] [+11] [+52] [+28] [ +0]
  1     2     3     4     5     6     7

এখন, আমরা সেই বালতিটিতে উপযুক্ত পরিমাণ যুক্ত করে সময় হে (1) এর মধ্যে একটি বালতির মধ্যে ফ্রিকোয়েন্সি বাড়িয়ে তুলতে পারি। যাইহোক, এখন দেখার জন্য মোট ব্যয়টি ও (এন) হয়ে যায়, যেহেতু আমাদের সমস্ত ছোট বালতিতে মানগুলি যোগ করে বালতিতে মোট সংগ্রহ করতে হয়।

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

এটি করার একটি উপায় হ'ল বালতির অ্যারে থেকে নোডের বাইনারি ট্রি হয়ে উপস্থাপনাটি পরিবর্তন করা। প্রতিটি নোড এমন একটি মান দিয়ে টীকায়িত করা হবে যা প্রদত্ত নোডের বামে সমস্ত নোডের সম্মিলিত যোগফলকে উপস্থাপন করে। উদাহরণস্বরূপ, ধরুন আমরা এই নোডগুলি থেকে নিম্নলিখিত বাইনারি গাছ তৈরি করেছি:

             4
          /     \
         2       6
        / \     / \
       1   3   5   7

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

Before:
[ +5] [ +1] [+15] [+11] [+52] [+28] [ +0]
  1     2     3     4     5     6     7

After:
                 4
               [+32]
              /     \
           2           6
         [ +6]       [+80]
         /   \       /   \
        1     3     5     7
      [ +5] [+15] [+52] [ +0]

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

উদাহরণস্বরূপ, ধরুন আমরা 3 টির জন্য যোগফলটি দেখতে চাই so এটি করার জন্য, আমরা নিম্নলিখিতটি করি:

  • মূল থেকে শুরু করুন (4) কাউন্টার 0
  • নোডে বাম দিকে যান (2) কাউন্টার 0
  • নোডের ডানদিকে যান (3) কাউন্টার 0 + 6 = 6।
  • নোড (3) সন্ধান করুন। কাউন্টারটি 6 + 15 = 21।

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

  • নোড (3) থেকে শুরু করুন। কাউন্টার 15।
  • নোডে উপরের দিকে যান (2)। কাউন্টারটি 15 + 6 = 21।
  • নোডে উপরের দিকে যান (4) কাউন্টার 21।

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

উদাহরণস্বরূপ, নোড 1 এর ফ্রিকোয়েন্সি পাঁচ দ্বারা বৃদ্ধি করার জন্য, আমরা নিম্নলিখিতটি করব:

                 4
               [+32]
              /     \
           2           6
         [ +6]       [+80]
         /   \       /   \
      > 1     3     5     7
      [ +5] [+15] [+52] [ +0]

নোড 1 এ শুরু করে, এর ফ্রিকোয়েন্সি পেতে 5 বৃদ্ধি করুন

                 4
               [+32]
              /     \
           2           6
         [ +6]       [+80]
         /   \       /   \
      > 1     3     5     7
      [+10] [+15] [+52] [ +0]

এখন, এর পিতামাতার কাছে যান:

                 4
               [+32]
              /     \
         > 2           6
         [ +6]       [+80]
         /   \       /   \
        1     3     5     7
      [+10] [+15] [+52] [ +0]

আমরা বাম সন্তানের লিঙ্কটি উপরের দিকে অনুসরণ করেছি, সুতরাং আমরা এই নোডের ফ্রিকোয়েন্সিটিও বাড়িয়েছি:

                 4
               [+32]
              /     \
         > 2           6
         [+11]       [+80]
         /   \       /   \
        1     3     5     7
      [+10] [+15] [+52] [ +0]

আমরা এখন এর পিতামাতার কাছে যাই:

               > 4
               [+32]
              /     \
           2           6
         [+11]       [+80]
         /   \       /   \
        1     3     5     7
      [+10] [+15] [+52] [ +0]

এটি একটি বাম সন্তানের লিঙ্ক ছিল, সুতরাং আমরা পাশাপাশি এই নোডকে বাড়িয়েছি:

                 4
               [+37]
              /     \
           2           6
         [+11]       [+80]
         /   \       /   \
        1     3     5     7
      [+10] [+15] [+52] [ +0]

এবং এখন আমরা সম্পন্ন করেছি!

চূড়ান্ত পদক্ষেপটি এ থেকে একটি বাইনারি সূচকযুক্ত গাছে রূপান্তর করা এবং এটিই আমরা বাইনারি সংখ্যার সাথে মজাদার কিছু করতে পারি। আসুন বাইনারি এই গাছের প্রতিটি বালতি সূচকটি আবার লিখি:

                100
               [+37]
              /     \
          010         110
         [+11]       [+80]
         /   \       /   \
       001   011   101   111
      [+10] [+15] [+52] [ +0]

এখানে, আমরা একটি খুব, খুব শীতল পর্যবেক্ষণ করতে পারি। এই বাইনারি নম্বরগুলির মধ্যে যে কোনওটি নিন এবং সংখ্যায় সেট করা খুব শেষ 1টি সন্ধান করুন, তারপরে আসা সমস্ত বিটগুলি সহ সেই বিটটি বাদ দিন। আপনি এখন নিম্নলিখিত সঙ্গে বাকি:

              (empty)
               [+37]
              /     \
           0           1
         [+11]       [+80]
         /   \       /   \
        00   01     10   11
      [+10] [+15] [+52] [ +0]

এখানে একটি সত্যই, সত্যিই দুর্দান্ত পর্যবেক্ষণ: আপনি যদি 0 ব্যবহার করে "বাম" এবং 1 টি মানে "ডান" ব্যবহার করেন, তবে প্রতিটি সংখ্যার বাকী বিটগুলি কীভাবে মূল থেকে শুরু করবেন এবং তারপরে সেই সংখ্যায় চলে যেতে হবে তা বানান করে। উদাহরণস্বরূপ, নোড 5 এর বাইনারি প্যাটার্ন 101 রয়েছে The শেষ 1টি চূড়ান্ত বিট হয়, তাই আমরা 10 এটিকে পেতে নামিয়ে দেব Indeed সত্যই, আপনি যদি মূল থেকে শুরু করেন তবে ডানদিকে যান (1), তারপরে বাম দিকে যান (0), আপনি শেষ করুন নোড 5 এ!

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

মূল কৌশলটি এই নিখুঁত বাইনারি গাছের নিম্নোক্ত সম্পত্তি:

নোড এন দেওয়া হয়েছে, যে ডানে আমরা ডানদিকে যাব সেখানে ফিরে যাওয়ার অ্যাক্সেস পাথের পরবর্তী নোডটি এন এর বাইনারি উপস্থাপনা গ্রহণ করে এবং শেষ 1 টি সরিয়ে দেওয়া হবে।

উদাহরণস্বরূপ, নোড for, যা ১১১ এর অ্যাক্সেস পাথটি একবার দেখুন is উপরের দিকে ডান পয়েন্টার অনুসরণ করে যে রুটটি আমরা গ্রহণ করি তার মূল অ্যাক্সেস পাথের নোডগুলি হ'ল

  • নোড 7: 111
  • নোড 6: 110
  • নোড 4: 100

এগুলি সবই সঠিক লিঙ্ক। আমরা যদি নোড 3, যা 011 এর অ্যাক্সেসের পথটি গ্রহণ করি এবং আমরা যে নোডগুলিতে ডানদিকে যাই সেদিকে নজর দিলে আমরা পাই

  • নোড 3: 011
  • নোড 2: 010
  • (নোড ৪: ১০০, যা একটি বাম লিঙ্ক অনুসরণ করে)

এর অর্থ হ'ল আমরা খুব, খুব দক্ষতার সাথে নীচের মতো একটি নোড পর্যন্ত সংযোজক যোগফলটি গণনা করতে পারি:

  • বাইনারি মধ্যে নোড এন লিখুন।
  • কাউন্টারে 0 তে সেট করুন।
  • N ≠ 0 করার সময় নিম্নলিখিতটি পুনরাবৃত্তি করুন:
    • নোডে মান যোগ করুন।
    • এন থেকে ডানদিকের 1 বিট সাফ করুন।

একইভাবে, আসুন আমরা কীভাবে একটি আপডেট পদক্ষেপ করব তা চিন্তা করি। এটি করার জন্য, আমরা মূলটিতে ফিরে অ্যাক্সেসের পথটি অনুসরণ করতে চাই এবং সমস্ত নোডকে আপডেট করে যেখানে আমরা বাম লিঙ্কটিকে উপরের দিকে অনুসরণ করেছি। আমরা এটি উপরোক্ত অ্যালগরিদমটি মূলত করেই করতে পারি, তবে সমস্ত 1 এর 0 এবং 0 এর 1 এ চলেছি।

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

আশাকরি এটা সাহায্য করবে!



আপনি দ্বিতীয় অনুচ্ছেদে আমাকে হারিয়েছেন। 7 টি বিভিন্ন উপাদানের সংশ্লেষিত ফ্রিকোয়েন্সি বলতে কী বোঝ?
জেসন গোমেট

20
ইন্টারনেটে আমি যে সকল উত্স খুঁজে পেয়েছি তার মধ্যে এটি এখন পর্যন্ত এই বিষয়টিতে সবচেয়ে ভাল ব্যাখ্যাটি পড়েছি। সাবাশ !
আনমল সিং জাগি 19

2
ফেনউইক কীভাবে এই স্মার্টটি পেল?
রকস্টার

1
এটি খুব দুর্দান্ত ব্যাখ্যা তবে ফেনউইকের নিজস্ব কাগজের মতো প্রতিটি ব্যাখ্যা হিসাবে একই সমস্যায় ভুগছে!
দার্থপাগিয়াস

3

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

ফেনউইক কেবল বলেছিলেন যে জিজ্ঞাসাবাদ গাছের প্রতিটি নোডের দায়িত্বের সীমাটি তার শেষ সেট বিট অনুসারে হবে:

ফেনউইক ট্রি নোডের দায়িত্ব

যেমন 6== এর শেষ সেট বিট হিসাবে 00110এটি একটি "2-বিট" এটি 2 নোডের ব্যাপ্তির জন্য দায়ী। 12== এর জন্য 01100এটি একটি "4-বিট", সুতরাং এটি 4 টি নোডের জন্য দায়বদ্ধ হবে।

সুতরাং F(12)== জিজ্ঞাসা করার সময় F(01100), আমরা একের পর এক বিটগুলি কেটে ফেলি F(9:12) + F(1:8)। এটি প্রায় কোনও কঠোর প্রমাণ নয়, তবে আমি মনে করি এটি কেবল স্পষ্টভাবে সংখ্যার অক্ষের উপর রাখলে এবং নিখুঁত বাইনারি গাছে নয়, প্রতিটি নোডের কী কী দায়িত্ব থাকে এবং কেন অনুসন্ধানের ব্যয়ের সংখ্যার সমান হয়? বিট সেট করুন।

এটি এখনও অস্পষ্ট থাকলে কাগজটি খুব প্রস্তাবিত।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.