সি ++ ভেক্টরগুলিতে পুশ_ব্যাক কেন ধ্রুবক অর্জিত হয়?


23

আমি সি ++ শিখছি এবং লক্ষ্য করেছি যে ভেক্টরদের জন্য পুশব্যাক ফাংশনের চলমান সময়টি ধ্রুবক "অ্যামোরিটাইজড" is ডকুমেন্টেশনে আরও উল্লেখ করা হয়েছে যে "যদি পুনরায় স্থানান্তর ঘটে তবে পুনরায় স্থানটি সম্পূর্ণ আকারে রৈখিক পর্যন্ত আপ হয়" "

এর অর্থ পশব্যাক ফাংশনটি , যেখানে ভেক্টরের দৈর্ঘ্য? সর্বোপরি, আমরা খারাপের বিশ্লেষণে আগ্রহী, তাই না?O(n)n

আমার ধারণা, অত্যন্ত গুরুত্বপূর্ণ, "amorised" বিশেষণ কীভাবে চলমান সময়কে পরিবর্তন করে তা আমি বুঝতে পারি না।


র‌্যাম মেশিনের সাহায্যে মেমরির বাইটগুলি বরাদ্দ করা কোনও ( এন ) ক্রিয়াকলাপ নয় - এটি বেশ ধ্রুবক সময় হিসাবে বিবেচিত হয়। এনহে(এন)
usul

উত্তর:


24

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

প্রদত্ত সর্বাধিক সাধারণ উদাহরণগুলির মধ্যে একটি হ'ল মাল্টিপপ ক্রিয়াকলাপের স্ট্যাকের বিশ্লেষণ যা উপাদানগুলি পপ করে। মাল্টিপপের একটি নির্লজ্জ বিশ্লেষণ বলবে যে সবচেয়ে খারাপ ক্ষেত্রে মাল্টিপপ অবশ্যই সময় নিতে হবে যেহেতু এটি স্ট্যাকের সমস্ত উপাদান পপ করতে পারে। তবে, আপনি যদি ক্রিয়াকলাপগুলির ক্রমটি লক্ষ্য করেন তবে আপনি লক্ষ্য করবেন যে পপসের সংখ্যা পুশের সংখ্যার বেশি হতে পারে না। সুতরাং কোন ক্রম উপর অপারেশন পপ সংখ্যা অতিক্রম করতে পারে না , এবং তাই multipop রান সময় amortized যদিও মাঝে মাঝে একটি একক কল আরও বেশি সময় লাগতে পারে।হে(এন)এনহে(এন)হে(1)

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

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


12

যদিও @ মার্ক একটি দুর্দান্ত বিশ্লেষণ দিয়েছেন (যা আমি মনে করি) একটি দুর্দান্ত বিশ্লেষণ দিয়েছে, কিছু লোক হয়তো কিছুটা ভিন্ন কোণ থেকে জিনিসগুলি বিবেচনা করতে পছন্দ করতে পারে।

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

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

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

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

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

দ্বিতীয়ত, আপনি যদি একবারে কেবল একটি পুরাতন উপাদান অনুলিপি করেন, অ্যারেতে সূচি তৈরি করা আরও কিছুটা জটিল হবে - প্রতিটি সূচীকরণ ক্রিয়াকলাপটি নির্ধারণ করতে হবে যে প্রদত্ত সূচিতে থাকা উপাদানটি বর্তমানে মেমরির পুরানো ব্লকের মধ্যে রয়েছে কিনা নতুন একটি. এটি কোনও উপায়ে মারাত্মক জটিল নয়, তবে অ্যারের সাথে সূচিকরণের মতো প্রাথমিক ক্রিয়াকলাপের জন্য প্রায় কোনও ধীর গতি উল্লেখযোগ্য হতে পারে।

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

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


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