டேட்டா ஸ்ட்ரக்சர்களை செயல்படுத்தி பகுப்பாய்வு செய்வதன் மூலம் ஜாவாஸ்கிரிப்ட் செயல்திறனில் தேர்ச்சி பெறுங்கள். இந்த விரிவான வழிகாட்டி Arrays, Objects, Trees மற்றும் பலவற்றை நடைமுறைக் குறியீட்டு எடுத்துக்காட்டுகளுடன் விளக்குகிறது.
ஜாவாஸ்கிரிப்ட் அல்காரிதம் செயல்படுத்தல்: டேட்டா ஸ்ட்ரக்சர் செயல்திறன் குறித்த ஒரு ஆழமான பார்வை
வலை மேம்பாட்டு உலகில், ஜாவாஸ்கிரிப்ட் கிளையன்ட்-சைடில் மறுக்கமுடியாத ராஜாவாகவும், சர்வர்-சைடில் ஒரு ஆதிக்க சக்தியாகவும் உள்ளது. அற்புதமான பயனர் அனுபவங்களை உருவாக்க நாம் பெரும்பாலும் ஃபிரேம்வொர்க்குகள், லைப்ரரிகள் மற்றும் புதிய மொழி அம்சங்களில் கவனம் செலுத்துகிறோம். இருப்பினும், ஒவ்வொரு மெருகூட்டப்பட்ட UI மற்றும் வேகமான API-யின் கீழும் டேட்டா ஸ்ட்ரக்சர்கள் மற்றும் அல்காரிதம்களின் அடித்தளம் உள்ளது. சரியான ஒன்றைத் தேர்ந்தெடுப்பது, மின்னல் வேகமான செயலிக்கும் அழுத்தத்தின் கீழ் நின்றுவிடும் செயலிக்கும் உள்ள வித்தியாசமாக இருக்கலாம். இது ஒரு கல்விப் பயிற்சி மட்டுமல்ல; இது நல்ல டெவலப்பர்களை சிறந்தவர்களிடமிருந்து பிரிக்கும் ஒரு நடைமுறைத் திறமையாகும்.
இந்த விரிவான வழிகாட்டி, உள்ளமைக்கப்பட்ட மெத்தட்களைப் பயன்படுத்துவதைத் தாண்டி, அவை ஏன் அவ்வாறு செயல்படுகின்றன என்பதைப் புரிந்துகொள்ள விரும்பும் தொழில்முறை ஜாவாஸ்கிரிப்ட் டெவலப்பர்களுக்கானது. நாம் ஜாவாஸ்கிரிப்டின் இயல்பான டேட்டா ஸ்ட்ரக்சர்களின் செயல்திறன் பண்புகளைப் பிரித்து ஆராய்வோம், கிளாசிக் வகைகளை புதிதாக செயல்படுத்துவோம், மற்றும் நிஜ உலகச் சூழ்நிலைகளில் அவற்றின் செயல்திறனை எவ்வாறு பகுப்பாய்வு செய்வது என்பதைக் கற்றுக்கொள்வோம். இதன் முடிவில், உங்கள் செயலியின் வேகம், அளவிடுதல் மற்றும் பயனர் திருப்தி ஆகியவற்றில் நேரடியாகத் தாக்கத்தை ஏற்படுத்தும் தகவலறிந்த முடிவுகளை எடுக்க நீங்கள் தயாராகிவிடுவீர்கள்.
செயல்திறனின் மொழி: பிக் ஓ குறியீடு ஒரு விரைவுப் பார்வை
குறியீட்டிற்குள் செல்வதற்கு முன், செயல்திறனைப் பற்றி விவாதிக்க நமக்கு ஒரு பொதுவான மொழி தேவை. அந்த மொழிதான் பிக் ஓ குறியீடு (Big O notation). உள்ளீட்டின் அளவு ('n' என பொதுவாகக் குறிக்கப்படுகிறது) வளரும்போது ஒரு அல்காரிதமின் இயக்க நேரம் அல்லது இடத் தேவை எவ்வாறு அளவிடப்படுகிறது என்பதற்கான மோசமான சூழ்நிலையை பிக் ஓ விவரிக்கிறது. இது மில்லி விநாடிகளில் வேகத்தை அளவிடுவது பற்றியது அல்ல, மாறாக ஒரு செயல்பாட்டின் வளர்ச்சிக் கோட்டைப் புரிந்துகொள்வது பற்றியது.
நீங்கள் சந்திக்கும் மிகவும் பொதுவான சிக்கல்தன்மைகள் இங்கே:
- O(1) - நிலையான நேரம் (Constant Time): செயல்திறனின் உச்சம். உள்ளீட்டுத் தரவின் அளவைப் பொருட்படுத்தாமல், செயல்பாட்டை முடிக்க எடுக்கும் நேரம் நிலையானது. ஒரு அரேவிலிருந்து அதன் இன்டெக்ஸ் மூலம் ஒரு பொருளைப் பெறுவது ஒரு சிறந்த எடுத்துக்காட்டு.
- O(log n) - மடக்கை நேரம் (Logarithmic Time): இயக்க நேரம் உள்ளீட்டின் அளவுக்கு ஏற்ப மடக்கை ரீதியாக வளர்கிறது. இது நம்பமுடியாத அளவிற்குத் திறமையானது. ஒவ்வொரு முறையும் நீங்கள் உள்ளீட்டின் அளவை இரட்டிப்பாக்கும்போது, செயல்பாடுகளின் எண்ணிக்கை ஒன்று மட்டுமே அதிகரிக்கிறது. ஒரு சமச்சீரான பைனரி சர்ச் ட்ரீயில் தேடுவது ஒரு முக்கிய எடுத்துக்காட்டு.
- O(n) - நேரியல் நேரம் (Linear Time): இயக்க நேரம் உள்ளீட்டின் அளவுக்கு நேர் விகிதத்தில் வளர்கிறது. உள்ளீட்டில் 10 பொருட்கள் இருந்தால், அது 10 'படிகள்' எடுக்கும். அதில் 1,000,000 பொருட்கள் இருந்தால், அது 1,000,000 'படிகள்' எடுக்கும். வரிசைப்படுத்தப்படாத அரேவில் ஒரு மதிப்பைத் தேடுவது ஒரு பொதுவான O(n) செயல்பாடு ஆகும்.
- O(n log n) - மடக்கை-நேரியல் நேரம் (Log-Linear Time): மெர்ஜ் சார்ட் மற்றும் ஹீப் சார்ட் போன்ற வரிசையாக்க அல்காரிதம்களுக்கு மிகவும் பொதுவான மற்றும் திறமையான சிக்கல்தன்மை இது. தரவு வளரும்போது இது நன்றாக அளவிடப்படுகிறது.
- O(n^2) - இருபடி நேரம் (Quadratic Time): இயக்க நேரம் உள்ளீட்டின் அளவின் வர்க்கத்திற்கு விகிதாசாரமாக இருக்கும். இங்கிருந்துதான் விஷயங்கள் வேகமாக மெதுவாகத் தொடங்குகின்றன. ஒரே தொகுப்பின் மீது உள்ளமைக்கப்பட்ட லூப்கள் ஒரு பொதுவான காரணமாகும். ஒரு எளிய பப்பிள் சார்ட் ஒரு சிறந்த எடுத்துக்காட்டு.
- O(2^n) - அடுக்குக்குறி நேரம் (Exponential Time): உள்ளீட்டில் சேர்க்கப்படும் ஒவ்வொரு புதிய உறுப்புடனும் இயக்க நேரம் இரட்டிப்பாகிறது. இந்த அல்காரிதம்கள் மிகச்சிறிய தரவுத்தொகுப்புகளைத் தவிர வேறு எதற்கும் பொதுவாக அளவிடக்கூடியவை அல்ல. மெமோடைசேஷன் இல்லாமல் ஃபைபோனச்சி எண்களின் ரெக்கர்சிவ் கணக்கீடு ஒரு எடுத்துக்காட்டு.
பிக் ஓ-வைப் புரிந்துகொள்வது அடிப்படையானது. இது ஒரு வரி குறியீட்டை இயக்காமலேயே செயல்திறனைக் கணிக்கவும், அளவின் சோதனையைத் தாங்கும் கட்டடக்கலை முடிவுகளை எடுக்கவும் நம்மை அனுமதிக்கிறது.
உள்ளமைக்கப்பட்ட ஜாவாஸ்கிரிப்ட் டேட்டா ஸ்ட்ரக்சர்கள்: ஒரு செயல்திறன் ஆய்வு
ஜாவாஸ்கிரிப்ட் ஒரு சக்திவாய்ந்த உள்ளமைக்கப்பட்ட டேட்டா ஸ்ட்ரக்சர் தொகுப்பை வழங்குகிறது. அவற்றின் பலம் மற்றும் பலவீனங்களைப் புரிந்துகொள்ள அவற்றின் செயல்திறன் பண்புகளைப் பகுப்பாய்வு செய்வோம்.
எங்கும் நிறைந்த அரே (Array)
ஜாவாஸ்கிரிப்ட் `Array` என்பது ஒருவேளை அதிகம் பயன்படுத்தப்படும் டேட்டா ஸ்ட்ரக்சர் ஆகும். இது மதிப்புகளின் வரிசைப்படுத்தப்பட்ட பட்டியல். తెరமறைவில், ஜாவாஸ்கிரிப்ட் இன்ஜின்கள் அரேக்களை பெரிதும் மேம்படுத்துகின்றன, ஆனால் அவற்றின் அடிப்படைக் குணங்கள் கணினி அறிவியல் கொள்கைகளைப் பின்பற்றுகின்றன.
- அணுகல் (இன்டெக்ஸ் மூலம்): O(1) - ஒரு குறிப்பிட்ட இன்டெக்ஸில் உள்ள ஒரு உறுப்பை அணுகுவது (எ.கா., `myArray[5]`) நம்பமுடியாத அளவிற்கு வேகமானது, ஏனெனில் கணினி அதன் நினைவக முகவரியை நேரடியாகக் கணக்கிட முடியும்.
- Push (இறுதியில் சேர்த்தல்): சராசரியாக O(1) - இறுதியில் ஒரு உறுப்பைச் சேர்ப்பது பொதுவாக மிகவும் வேகமானது. ஜாவாஸ்கிரிப்ட் இன்ஜின்கள் நினைவகத்தை முன்கூட்டியே ஒதுக்குகின்றன, எனவே இது வழக்கமாக ஒரு மதிப்பை அமைப்பது மட்டுமே. எப்போதாவது, அரேவின் அளவை மாற்றி நகலெடுக்க வேண்டியிருக்கும், இது ஒரு O(n) செயல்பாடு, ஆனால் இது அரிதாக இருப்பதால், சராசரிப்படுத்தப்பட்ட நேர சிக்கல்தன்மை O(1) ஆகும்.
- Pop (இறுதியிலிருந்து நீக்குதல்): O(1) - கடைசி உறுப்பை நீக்குவதும் மிகவும் வேகமானது, ஏனெனில் வேறு எந்த உறுப்புகளையும் மீண்டும் இன்டெக்ஸ் செய்யத் தேவையில்லை.
- Unshift (ஆரம்பத்தில் சேர்த்தல்): O(n) - இது ஒரு செயல்திறன் பொறி! ஆரம்பத்தில் ஒரு உறுப்பைச் சேர்க்க, அரேவில் உள்ள மற்ற ஒவ்வொரு உறுப்பும் ஒரு நிலை வலதுபுறம் நகர்த்தப்பட வேண்டும். இதன் செலவு அரேவின் அளவுக்கு ஏற்ப நேரியல் ரீதியாக வளர்கிறது.
- Shift (ஆரம்பத்திலிருந்து நீக்குதல்): O(n) - இதேபோல், முதல் உறுப்பை நீக்குவதற்கு, அடுத்தடுத்த அனைத்து உறுப்புகளையும் ஒரு நிலை இடதுபுறம் நகர்த்த வேண்டும். செயல்திறன்-முக்கியமான லூப்களில் பெரிய அரேக்களில் இதைத் தவிர்க்கவும்.
- தேடல் (எ.கா., `indexOf`, `includes`): O(n) - ஒரு உறுப்பைக் கண்டுபிடிக்க, ஜாவாஸ்கிரிப்ட் ஒரு பொருத்தம் காணும் வரை ஆரம்பத்திலிருந்து ஒவ்வொரு உறுப்பையும் சரிபார்க்க வேண்டியிருக்கும்.
- Splice / Slice: O(n) - நடுவில் செருகுதல்/நீக்குதல் அல்லது துணை அரேக்களை உருவாக்குவதற்கான இரண்டு மெத்தட்களுக்கும் பொதுவாக அரேவின் ஒரு பகுதியை மீண்டும் இன்டெக்ஸ் செய்வது அல்லது நகலெடுப்பது தேவைப்படுகிறது, இது அவற்றை நேரியல் நேர செயல்பாடுகளாக மாற்றுகிறது.
முக்கிய குறிப்பு: அரேக்கள் இன்டெக்ஸ் மூலம் விரைவான அணுகலுக்கும், இறுதியில் பொருட்களைச் சேர்ப்பதற்கும்/நீக்குவதற்கும் அருமையானவை. ஆரம்பத்திலோ அல்லது நடுவிலோ பொருட்களைச் சேர்ப்பதற்கும்/நீக்குவதற்கும் அவை திறனற்றவை.
பன்முகத்தன்மை வாய்ந்த ஆப்ஜெக்ட் (ஹாஷ் மேப்பாக)
ஜாவாஸ்கிரிப்ட் ஆப்ஜெக்ட்கள் கீ-வேல்யூ ஜோடிகளின் தொகுப்புகள். அவை பல விஷயங்களுக்குப் பயன்படுத்தப்படலாம் என்றாலும், ஒரு டேட்டா ஸ்ட்ரக்சராக அவற்றின் முதன்மைப் பங்கு ஒரு ஹாஷ் மேப் (அல்லது டிக்ஷனரி) ஆகும். ஒரு ஹாஷ் செயல்பாடு ஒரு கீயை எடுத்து, அதை ஒரு இன்டெக்ஸாக மாற்றி, அந்த இடத்தில் மதிப்பை நினைவகத்தில் சேமிக்கிறது.
- செருகுதல் / புதுப்பித்தல்: சராசரியாக O(1) - ஒரு புதிய கீ-வேல்யூ ஜோடியைச் சேர்ப்பது அல்லது ஏற்கனவே உள்ளதைப் புதுப்பிப்பது ஹாஷைக் கணக்கிட்டு தரவை வைப்பதை உள்ளடக்கியது. இது பொதுவாக நிலையான நேரம்.
- நீக்குதல்: சராசரியாக O(1) - ஒரு கீ-வேல்யூ ஜோடியை நீக்குவதும் சராசரியாக ஒரு நிலையான நேர செயல்பாடு ஆகும்.
- கண்டறிதல் (கீ மூலம் அணுகல்): சராசரியாக O(1) - இதுதான் ஆப்ஜெக்ட்களின் சூப்பர் பவர். ஒரு மதிப்பை அதன் கீ மூலம் மீட்டெடுப்பது, ஆப்ஜெக்ட்டில் எத்தனை கீகள் இருந்தாலும், மிகவும் வேகமானது.
"சராசரியாக" என்ற சொல் முக்கியமானது. ஒரு ஹாஷ் மோதல் (இரண்டு வெவ்வேறு கீகள் ஒரே ஹாஷ் இன்டெக்ஸை உருவாக்கும்) என்ற அரிதான வழக்கில், அந்த இன்டெக்ஸில் உள்ள ஒரு சிறிய உருப்படிகளின் பட்டியலை அமைப்பு மீண்டும் செய்ய வேண்டியிருப்பதால் செயல்திறன் O(n) ஆகக் குறையக்கூடும். இருப்பினும், நவீன ஜாவாஸ்கிரிப்ட் இன்ஜின்கள் சிறந்த ஹாஷிங் அல்காரிதம்களைக் கொண்டுள்ளன, இது பெரும்பாலான பயன்பாடுகளுக்கு ஒரு பிரச்சினையாக இருக்காது.
ES6-இன் ஆற்றல் மையங்கள்: செட் (Set) மற்றும் மேப் (Map)
ES6 ஆனது `Map` மற்றும் `Set`-ஐ அறிமுகப்படுத்தியது, இது சில பணிகளுக்கு ஆப்ஜெக்ட்கள் மற்றும் அரேக்களைப் பயன்படுத்துவதற்குப் பதிலாக மேலும் சிறப்பு வாய்ந்த மற்றும் பெரும்பாலும் அதிக செயல்திறன் கொண்ட மாற்றுகளை வழங்குகிறது.
Set: ஒரு `Set` என்பது தனித்துவமான மதிப்புகளின் தொகுப்பாகும். இது நகல்கள் இல்லாத ஒரு அரேவைப் போன்றது.
- `add(value)`: சராசரியாக O(1).
- `has(value)`: சராசரியாக O(1). இது அரேவின் `includes()` மெத்தடை விட (இது O(n)) அதன் முக்கிய நன்மை.
- `delete(value)`: சராசரியாக O(1).
நீங்கள் தனித்துவமான உருப்படிகளின் பட்டியலைச் சேமித்து, அவற்றின் இருப்பை அடிக்கடி சரிபார்க்க வேண்டியிருக்கும் போது ஒரு `Set`-ஐப் பயன்படுத்தவும். உதாரணமாக, ஒரு பயனர் ஐடி ஏற்கனவே செயலாக்கப்பட்டுள்ளதா என்பதைச் சரிபார்க்க.
Map: ஒரு `Map` ஒரு ஆப்ஜெக்ட்டைப் போன்றது, ஆனால் சில முக்கியமான நன்மைகளுடன். இது கீ-வேல்யூ ஜோடிகளின் தொகுப்பாகும், இங்கு கீகள் எந்தவொரு டேட்டா வகையாகவும் இருக்கலாம் (ஆப்ஜெக்ட்களில் உள்ளது போல் ஸ்டிரிங் அல்லது சிம்பல்களாக மட்டும் அல்ல). இது செருகப்பட்ட வரிசையையும் பராமரிக்கிறது.
- `set(key, value)`: சராசரியாக O(1).
- `get(key)`: சராசரியாக O(1).
- `has(key)`: சராசரியாக O(1).
- `delete(key)`: சராசரியாக O(1).
உங்களுக்கு ஒரு டிக்ஷனரி/ஹாஷ் மேப் தேவைப்படும்போதும், உங்கள் கீகள் ஸ்டிரிங்குகளாக இல்லாமல் இருக்கலாம் அல்லது உறுப்புகளின் வரிசைக்கு நீங்கள் உத்தரவாதம் அளிக்க வேண்டியிருக்கும்போதும் ஒரு `Map`-ஐப் பயன்படுத்தவும். இது பொதுவாக ஒரு சாதாரண ஆப்ஜெக்ட்டை விட ஹாஷ் மேப் நோக்கங்களுக்காக மிகவும் வலுவான தேர்வாகக் கருதப்படுகிறது.
கிளாசிக் டேட்டா ஸ்ட்ரக்சர்களை புதிதாக உருவாக்கி பகுப்பாய்வு செய்தல்
செயல்திறனை உண்மையாகப் புரிந்துகொள்ள, இந்த அமைப்புகளை நீங்களே உருவாக்குவதற்கு மாற்று இல்லை. இது சம்பந்தப்பட்ட வர்த்தகப் பரிமாற்றங்கள் பற்றிய உங்கள் புரிதலை ஆழமாக்குகிறது.
லிங்க்டு லிஸ்ட்: அரேவின் தளைகளிலிருந்து தப்பித்தல்
ஒரு லிங்க்டு லிஸ்ட் என்பது ஒரு நேரியல் டேட்டா ஸ்ட்ரக்சர் ஆகும், அங்கு உறுப்புகள் தொடர்ச்சியான நினைவக இடங்களில் சேமிக்கப்படுவதில்லை. அதற்குப் பதிலாக, ஒவ்வொரு உறுப்பும் ('நோட்') அதன் தரவையும் வரிசையில் அடுத்த நோடுக்கான ஒரு பாயிண்டரையும் கொண்டுள்ளது. இந்த அமைப்பு அரேக்களின் பலவீனங்களை நேரடியாக நிவர்த்தி செய்கிறது.
ஒரு சிங்கிள் லிங்க்டு லிஸ்ட் நோட் மற்றும் லிஸ்ட்-இன் செயல்படுத்தல்:
// Node class represents each element in the list class Node { constructor(data, next = null) { this.data = data; this.next = next; } } // LinkedList class manages the nodes class LinkedList { constructor() { this.head = null; // The first node this.size = 0; } // Insert at the beginning (pre-pend) insertFirst(data) { this.head = new Node(data, this.head); this.size++; } // ... other methods like insertLast, insertAt, getAt, removeAt ... }
அரேவுக்கு எதிரான செயல்திறன் பகுப்பாய்வு:
- ஆரம்பத்தில் செருகுதல்/நீக்குதல்: O(1). இதுதான் லிங்க்டு லிஸ்ட்டின் மிகப்பெரிய நன்மை. ஆரம்பத்தில் ஒரு புதிய நோடைச் சேர்க்க, நீங்கள் அதை உருவாக்கி அதன் `next`-ஐ பழைய `head`-க்கு சுட்டிக்காட்டினால் போதும். மீண்டும் இன்டெக்ஸ் செய்யத் தேவையில்லை! இது அரேவின் O(n) `unshift` மற்றும் `shift`-ஐ விட மிகப்பெரிய முன்னேற்றம்.
- இறுதியில்/நடுவில் செருகுதல்/நீக்குதல்: சரியான நிலையைக் கண்டுபிடிக்க பட்டியலை கடந்து செல்ல வேண்டியிருப்பதால், இது ஒரு O(n) செயல்பாடு ஆகும். இறுதியில் சேர்ப்பதற்கு ஒரு அரே பெரும்பாலும் வேகமானது. ஒரு டபுள் லிங்க்டு லிஸ்ட் (அடுத்த மற்றும் முந்தைய நோட்களுக்கான பாயிண்டர்களுடன்) நீக்கப்படும் நோடிற்கான ஒரு ரெஃபரன்ஸ் உங்களிடம் ஏற்கனவே இருந்தால் நீக்குதலை மேம்படுத்த முடியும், இது அதை O(1) ஆக்குகிறது.
- அணுகல்/தேடல்: O(n). நேரடி இன்டெக்ஸ் இல்லை. 100-வது உறுப்பைக் கண்டுபிடிக்க, நீங்கள் `head`-இல் தொடங்கி 99 நோட்களைக் கடந்து செல்ல வேண்டும். இது அரேவின் O(1) இன்டெக்ஸ் அணுகலுடன் ஒப்பிடும்போது ஒரு குறிப்பிடத்தக்க தீமையாகும்.
ஸ்டாக்குகள் மற்றும் க்யூக்கள்: வரிசை மற்றும் ஓட்டத்தை நிர்வகித்தல்
ஸ்டாக்குகள் மற்றும் க்யூக்கள் அவற்றின் அடிப்படைச் செயலாக்கத்தைக் காட்டிலும் அவற்றின் நடத்தையால் வரையறுக்கப்பட்ட சுருக்கமான தரவு வகைகள். பணிகள், செயல்பாடுகள் மற்றும் தரவு ஓட்டத்தை நிர்வகிப்பதில் அவை முக்கியமானவை.
ஸ்டாக் (LIFO - Last-In, First-Out): தட்டுகளின் அடுக்கை கற்பனை செய்து பாருங்கள். நீங்கள் ஒரு தட்டை மேலே சேர்க்கிறீர்கள், மற்றும் நீங்கள் ஒரு தட்டை மேலிருந்து அகற்றுகிறீர்கள். நீங்கள் கடைசியாக வைத்ததுதான் நீங்கள் முதலில் எடுப்பது.
- அரேவுடன் செயல்படுத்தல்: அற்பமானது மற்றும் திறமையானது. ஸ்டாக்கில் சேர்க்க `push()`-ஐயும், அகற்ற `pop()`-ஐயும் பயன்படுத்தவும். இரண்டுமே O(1) செயல்பாடுகள்.
- லிங்க்டு லிஸ்ட்டுடன் செயல்படுத்தல்: இதுவும் மிகவும் திறமையானது. சேர்க்க `insertFirst()`-ஐயும் (push), அகற்ற `removeFirst()`-ஐயும் (pop) பயன்படுத்தவும். இரண்டுமே O(1) செயல்பாடுகள்.
க்யூ (FIFO - First-In, First-Out): ஒரு டிக்கெட் கவுண்டரில் ஒரு வரிசையை கற்பனை செய்து பாருங்கள். வரிசையில் முதலில் வருபவரே முதலில் சேவை செய்யப்படுகிறார்.
- அரேவுடன் செயல்படுத்தல்: இது ஒரு செயல்திறன் பொறி! க்யூவின் இறுதியில் சேர்க்க (enqueue), நீங்கள் `push()`-ஐப் பயன்படுத்துகிறீர்கள் (O(1)). ஆனால் முன்பக்கத்திலிருந்து அகற்ற (dequeue), நீங்கள் `shift()`-ஐப் பயன்படுத்த வேண்டும் (O(n)). இது பெரிய க்யூக்களுக்கு திறனற்றது.
- லிங்க்டு லிஸ்ட்டுடன் செயல்படுத்தல்: இதுவே சிறந்த செயல்படுத்தல். பட்டியலின் இறுதிக்கு (tail) ஒரு நோடைச் சேர்ப்பதன் மூலம் Enqueue செய்யவும், மற்றும் பட்டியலின் தொடக்கத்திலிருந்து (head) நோடை அகற்றுவதன் மூலம் Dequeue செய்யவும். head மற்றும் tail இரண்டிற்கும் ரெஃபரன்ஸ்கள் இருப்பதால், இரண்டு செயல்பாடுகளும் O(1) ஆகும்.
பைனரி சர்ச் ட்ரீ (BST): வேகத்திற்காக ஒழுங்கமைத்தல்
உங்களிடம் வரிசைப்படுத்தப்பட்ட தரவு இருக்கும்போது, நீங்கள் O(n) தேடலை விட மிகச் சிறப்பாகச் செய்ய முடியும். ஒரு பைனரி சர்ச் ட்ரீ என்பது ஒரு நோட்-அடிப்படையிலான ட்ரீ டேட்டா ஸ்ட்ரக்சர் ஆகும், அங்கு ஒவ்வொரு நோடிற்கும் ஒரு மதிப்பு, ஒரு இடது குழந்தை மற்றும் ஒரு வலது குழந்தை உள்ளது. முக்கியப் பண்பு என்னவென்றால், எந்தவொரு கொடுக்கப்பட்ட நோடிற்கும், அதன் இடது துணை மரத்தில் உள்ள அனைத்து மதிப்புகளும் அதன் மதிப்பை விடக் குறைவாகவும், அதன் வலது துணை மரத்தில் உள்ள அனைத்து மதிப்புகளும் அதிகமாகவும் இருக்கும்.
ஒரு BST நோட் மற்றும் ட்ரீயின் செயல்படுத்தல்:
class Node { constructor(data) { this.data = data; this.left = null; this.right = null; } } class BinarySearchTree { constructor() { this.root = null; } insert(data) { const newNode = new Node(data); if (this.root === null) { this.root = newNode; } else { this.insertNode(this.root, newNode); } } // Helper recursive function insertNode(node, newNode) { if (newNode.data < node.data) { if (node.left === null) { node.left = newNode; } else { this.insertNode(node.left, newNode); } } else { if (node.right === null) { node.right = newNode; } else { this.insertNode(node.right, newNode); } } } // ... search and remove methods ... }
செயல்திறன் பகுப்பாய்வு:
- தேடல், செருகுதல், நீக்குதல்: ஒரு சமச்சீரான ட்ரீயில், இந்த செயல்பாடுகள் அனைத்தும் O(log n) ஆகும். ஏனென்றால், ஒவ்வொரு ஒப்பீட்டிலும், மீதமுள்ள நோட்களில் பாதியை நீங்கள் நீக்குகிறீர்கள். இது மிகவும் சக்தி வாய்ந்தது மற்றும் அளவிடக்கூடியது.
- சமநிலையற்ற ட்ரீ சிக்கல்: O(log n) செயல்திறன் முற்றிலும் ட்ரீ சமச்சீராக இருப்பதைப் பொறுத்தது. நீங்கள் வரிசைப்படுத்தப்பட்ட தரவை (எ.கா., 1, 2, 3, 4, 5) ஒரு எளிய BST-இல் செருகினால், அது ஒரு லிங்க்டு லிஸ்ட்டாகச் சிதைந்துவிடும். எல்லா நோட்களும் வலது குழந்தைகளாக இருக்கும். இந்த மோசமான நிலையில், எல்லா செயல்பாடுகளுக்குமான செயல்திறன் O(n) ஆகக் குறைகிறது. இதனால்தான் AVL ட்ரீகள் அல்லது ரெட்-பிளாக் ட்ரீகள் போன்ற மேம்பட்ட சுய-சமநிலைப்படுத்தும் ட்ரீகள் உள்ளன, இருப்பினும் அவற்றை செயல்படுத்துவது மிகவும் சிக்கலானது.
கிராஃப்கள்: சிக்கலான உறவுகளை மாதிரியாக்குதல்
ஒரு கிராஃப் என்பது விளிம்புகளால் இணைக்கப்பட்ட நோட்களின் (செங்குத்துகள்) தொகுப்பாகும். நெட்வொர்க்குகளை மாதிரியாக்குவதற்கு அவை சரியானவை: சமூக வலைப்பின்னல்கள், சாலை வரைபடங்கள், கணினி நெட்வொர்க்குகள் போன்றவை. குறியீட்டில் ஒரு கிராஃபை நீங்கள் எவ்வாறு பிரதிநிதித்துவப்படுத்த தேர்வு செய்கிறீர்கள் என்பது பெரிய செயல்திறன் தாக்கங்களைக் கொண்டுள்ளது.
அட்ஜசென்சி மேட்ரிக்ஸ்: V x V அளவிலான ஒரு 2D அரே (மேட்ரிக்ஸ்) (இங்கு V என்பது செங்குத்துகளின் எண்ணிக்கை). வெர்டெக்ஸ் `i` இலிருந்து `j` க்கு ஒரு விளிம்பு இருந்தால் `matrix[i][j] = 1`, இல்லையெனில் 0.
- நன்மைகள்: இரண்டு செங்குத்துகளுக்கு இடையில் ஒரு விளிம்பு உள்ளதா என்பதைச் சரிபார்ப்பது O(1) ஆகும்.
- தீமைகள்: O(V^2) இடத்தைப் பயன்படுத்துகிறது, இது ஸ்பார்ஸ் கிராஃப்களுக்கு (சில விளிம்புகளுடன் கூடிய கிராஃப்கள்) மிகவும் திறனற்றது. ஒரு வெர்டெக்ஸ்சின் அனைத்து அண்டை நாடுகளையும் கண்டுபிடிக்க O(V) நேரம் ஆகும்.
அட்ஜசென்சி லிஸ்ட்: பட்டியல்களின் ஒரு அரே (அல்லது மேப்). அரேவில் உள்ள இன்டெக்ஸ் `i` வெர்டெக்ஸ் `i`-ஐக் குறிக்கிறது, மற்றும் அந்த இன்டெக்ஸில் உள்ள பட்டியல் `i` விளிம்பைக் கொண்ட அனைத்து செங்குத்துகளையும் கொண்டுள்ளது.
- நன்மைகள்: இடம் திறமையானது, O(V + E) இடத்தைப் பயன்படுத்துகிறது (இங்கு E என்பது விளிம்புகளின் எண்ணிக்கை). ஒரு வெர்டெக்ஸ்சின் அனைத்து அண்டை நாடுகளையும் கண்டுபிடிப்பது திறமையானது (அண்டை நாடுகளின் எண்ணிக்கைக்கு விகிதாசாரமாக).
- தீமைகள்: கொடுக்கப்பட்ட இரண்டு செங்குத்துகளுக்கு இடையில் ஒரு விளிம்பை சரிபார்க்க அதிக நேரம் ஆகலாம், O(log k) அல்லது O(k) வரை ஆகலாம், இங்கு k என்பது அண்டை நாடுகளின் எண்ணிக்கை.
வலையில் உள்ள பெரும்பாலான நிஜ-உலகப் பயன்பாடுகளுக்கு, கிராஃப்கள் ஸ்பார்ஸ் ஆக உள்ளன, இது அட்ஜசென்சி லிஸ்ட்டை மிகவும் பொதுவான மற்றும் செயல்திறன் மிக்க தேர்வாக ஆக்குகிறது.
நிஜ உலகில் நடைமுறை செயல்திறன் அளவீடு
கோட்பாட்டு பிக் ஓ ஒரு வழிகாட்டி, ஆனால் சில நேரங்களில் உங்களுக்கு கடினமான எண்கள் தேவை. உங்கள் குறியீட்டின் உண்மையான செயல்படுத்தல் நேரத்தை நீங்கள் எவ்வாறு அளவிடுகிறீர்கள்?
கோட்பாட்டிற்கு அப்பால்: உங்கள் குறியீட்டைத் துல்லியமாக நேரத்தைக் கணித்தல்
`Date.now()`-ஐப் பயன்படுத்த வேண்டாம். இது உயர்-துல்லியமான பெஞ்ச்மார்க்கிங்கிற்காக வடிவமைக்கப்படவில்லை. அதற்குப் பதிலாக, பிரவுசர்கள் மற்றும் Node.js இரண்டிலும் கிடைக்கும் பெர்ஃபார்மன்ஸ் API-ஐப் பயன்படுத்தவும்.
உயர்-துல்லியமான நேரக்கணிப்புக்கு `performance.now()`-ஐப் பயன்படுத்துதல்:
// Example: Comparing Array.unshift vs a LinkedList insertion const hugeArray = Array.from({ length: 100000 }, (_, i) => i); const hugeLinkedList = new LinkedList(); // Assuming this is implemented for(let i = 0; i < 100000; i++) { hugeLinkedList.insertLast(i); } // Test Array.unshift const startTimeArray = performance.now(); hugeArray.unshift(-1); const endTimeArray = performance.now(); console.log(`Array.unshift took ${endTimeArray - startTimeArray} milliseconds.`); // Test LinkedList.insertFirst const startTimeLL = performance.now(); hugeLinkedList.insertFirst(-1); const endTimeLL = performance.now(); console.log(`LinkedList.insertFirst took ${endTimeLL - startTimeLL} milliseconds.`);
இதை நீங்கள் இயக்கும்போது, ஒரு வியத்தகு வித்தியாசத்தைக் காண்பீர்கள். லிங்க்டு லிஸ்ட் செருகல் கிட்டத்தட்ட உடனடி ஆக இருக்கும், அதேசமயம் அரே அன்ஷிஃப்ட் குறிப்பிடத்தக்க அளவு நேரத்தை எடுக்கும், இது O(1) vs O(n) கோட்பாட்டை நடைமுறையில் நிரூபிக்கிறது.
V8 இன்ஜின் காரணி: நீங்கள் காணாதவை
உங்கள் ஜாவாஸ்கிரிப்ட் குறியீடு ஒரு வெற்றிடத்தில் இயங்காது என்பதை நினைவில் கொள்வது அவசியம். இது V8 (Chrome மற்றும் Node.js-இல்) போன்ற மிகவும் அதிநவீன இன்ஜின் மூலம் செயல்படுத்தப்படுகிறது. V8 நம்பமுடியாத JIT (Just-In-Time) தொகுப்பு மற்றும் மேம்படுத்தல் தந்திரங்களைச் செய்கிறது.
- மறைக்கப்பட்ட வகுப்புகள் (வடிவங்கள்): ஒரே வரிசையில் ஒரே பிராப்பர்ட்டி கீகளைக் கொண்ட ஆப்ஜெக்ட்களுக்கு V8 உகந்த 'வடிவங்களை' உருவாக்குகிறது. இது பிராப்பர்ட்டி அணுகலை கிட்டத்தட்ட அரே இன்டெக்ஸ் அணுகல் போல வேகமாக மாற்ற அனுமதிக்கிறது.
- இன்லைன் கேச்சிங்: V8 சில செயல்பாடுகளில் காணும் மதிப்புகளின் வகைகளை நினைவில் கொள்கிறது மற்றும் பொதுவான வழக்குக்கு உகந்ததாக்குகிறது.
இது உங்களுக்கு என்ன அர்த்தம்? சில நேரங்களில், கோட்பாட்டளவில் பிக் ஓ அடிப்படையில் மெதுவான ஒரு செயல்பாடு, இன்ஜின் மேம்படுத்தல்கள் காரணமாக சிறிய தரவுத்தொகுப்புகளுக்கு நடைமுறையில் வேகமாக இருக்கலாம். உதாரணமாக, மிகச் சிறிய `n`-க்கு, `shift()`-ஐப் பயன்படுத்தும் ஒரு அரே-அடிப்படையிலான க்யூ, நோட் ஆப்ஜெக்ட்களை உருவாக்கும் கூடுதல் சுமை மற்றும் V8-இன் உகந்த, நேட்டிவ் அரே செயல்பாடுகளின் மூல வேகம் காரணமாக, தனிப்பயனாக்கப்பட்ட லிங்க்டு லிஸ்ட் க்யூவை விட சிறப்பாக செயல்படக்கூடும். இருப்பினும், `n` பெரிதாக வளரும்போது பிக் ஓ எப்போதும் வெற்றி பெறும். அளவிடுதலுக்கான உங்கள் முதன்மை வழிகாட்டியாக எப்போதும் பிக் ஓ-வைப் பயன்படுத்தவும்.
இறுதிக் கேள்வி: நான் எந்த டேட்டா ஸ்ட்ரக்சரைப் பயன்படுத்த வேண்டும்?
கோட்பாடு சிறந்தது, ஆனால் அதை உறுதியான, உலகளாவிய மேம்பாட்டுச் சூழ்நிலைகளுக்குப் பயன்படுத்துவோம்.
-
சூழ்நிலை 1: ஒரு பயனரின் இசைப் பட்டியலை நிர்வகித்தல், அங்கு அவர்கள் பாடல்களைச் சேர்க்கலாம், நீக்கலாம் மற்றும் மறுவரிசைப்படுத்தலாம்.
பகுப்பாய்வு: பயனர்கள் அடிக்கடி பாடல்களை நடுவில் சேர்க்கிறார்கள்/நீக்குகிறார்கள். ஒரு அரேவுக்கு O(n) `splice` செயல்பாடுகள் தேவைப்படும். ஒரு டபுள் லிங்க்டு லிஸ்ட் இங்கே சிறந்ததாக இருக்கும். நோட்களுக்கான ஒரு ரெஃபரன்ஸ் உங்களிடம் இருந்தால், ஒரு பாடலை நீக்குவது அல்லது இரண்டு பாடல்களுக்கு இடையில் ஒரு பாடலைச் செருகுவது O(1) செயல்பாடாக மாறும், இது பெரிய பிளேலிஸ்ட்களுக்கு கூட UI-ஐ உடனடி உணர்வைத் தரும்.
-
சூழ்நிலை 2: API பதில்களுக்காக ஒரு கிளையன்ட்-சைட் கேச் உருவாக்குதல், அங்கு கீகள் வினவல் அளவுருக்களைக் குறிக்கும் சிக்கலான ஆப்ஜெக்ட்களாகும்.
பகுப்பாய்வு: கீகளின் அடிப்படையில் நமக்கு வேகமான தேடல்கள் தேவை. ஒரு சாதாரண ஆப்ஜெக்ட் தோல்வியடைகிறது, ஏனெனில் அதன் கீகள் ஸ்டிரிங்குகளாக மட்டுமே இருக்க முடியும். ஒரு Map சரியான தீர்வு. இது ஆப்ஜெக்ட்களை கீகளாக அனுமதிக்கிறது மற்றும் `get`, `set`, மற்றும் `has` ஆகியவற்றிற்கு சராசரியாக O(1) நேரத்தை வழங்குகிறது, இது அதை ஒரு உயர் செயல்திறன் கொண்ட கேச்சிங் மெக்கானிசமாக ஆக்குகிறது.
-
சூழ்நிலை 3: உங்கள் தரவுத்தளத்தில் உள்ள 1 மில்லியன் தற்போதைய மின்னஞ்சல்களுக்கு எதிராக 10,000 புதிய பயனர் மின்னஞ்சல்களின் ஒரு தொகுதியைச் சரிபார்த்தல்.
பகுப்பாய்வு: புதிய மின்னஞ்சல்கள் வழியாக லூப் செய்து, ஒவ்வொன்றிற்கும், தற்போதுள்ள மின்னஞ்சல்கள் அரேவில் `Array.includes()`-ஐப் பயன்படுத்துவது என்பது भोली அணுகுமுறை. இது O(n*m) ஆக இருக்கும், இது ஒரு பேரழிவு செயல்திறன் தடையாகும். சரியான அணுகுமுறை முதலில் 1 மில்லியன் தற்போதைய மின்னஞ்சல்களை ஒரு Set-இல் ஏற்றுவது (ஒரு O(m) செயல்பாடு). பின்னர், 10,000 புதிய மின்னஞ்சல்கள் வழியாக லூப் செய்து, ஒவ்வொன்றிற்கும் `Set.has()`-ஐப் பயன்படுத்தவும். இந்தச் சரிபார்ப்பு O(1) ஆகும். மொத்த சிக்கல்தன்மை O(n + m) ஆக மாறுகிறது, இது மிகவும் உயர்ந்தது.
-
சூழ்நிலை 4: ஒரு நிறுவன விளக்கப்படம் அல்லது ஒரு கோப்பு முறைமை எக்ஸ்ப்ளோரரை உருவாக்குதல்.
பகுப்பாய்வு: இந்தத் தரவு இயல்பாகவே படிநிலை அமைப்பில் உள்ளது. ஒரு ட்ரீ கட்டமைப்பு இயற்கையான பொருத்தம். ஒவ்வொரு நோடும் ஒரு ஊழியர் அல்லது ஒரு கோப்புறையைக் குறிக்கும், மற்றும் அதன் குழந்தைகள் அவர்களின் நேரடி அறிக்கைகள் அல்லது துணைக் கோப்புறைகளாக இருக்கும். பின்னர், டெப்த்-ஃபர்ஸ்ட் சர்ச் (DFS) அல்லது பிரெத்-ஃபர்ஸ்ட் சர்ச் (BFS) போன்ற டிராவர்சல் அல்காரிதம்களைப் பயன்படுத்தி இந்த படிநிலையைத் திறமையாக வழிநடத்தலாம் அல்லது காட்டலாம்.
முடிவுரை: செயல்திறன் ஒரு அம்சம்
செயல்திறன் மிக்க ஜாவாஸ்கிரிப்ட் எழுதுவது என்பது முன்கூட்டிய மேம்படுத்தல் அல்லது ஒவ்வொரு அல்காரிதத்தையும் மனப்பாடம் செய்வது பற்றியது அல்ல. இது நீங்கள் ஒவ்வொரு நாளும் பயன்படுத்தும் கருவிகளைப் பற்றிய ஆழமான புரிதலை வளர்ப்பது பற்றியது. அரேக்கள், ஆப்ஜெக்ட்கள், மேப்கள் மற்றும் செட்களின் செயல்திறன் பண்புகளை உள்வாங்குவதன் மூலமும், லிங்க்டு லிஸ்ட் அல்லது ட்ரீ போன்ற ஒரு கிளாசிக் கட்டமைப்பு எப்போது சிறந்த பொருத்தம் என்பதை அறிவதன் மூலமும், உங்கள் கைவினைத்திறனை நீங்கள் உயர்த்துகிறீர்கள்.
உங்கள் பயனர்களுக்கு பிக் ஓ குறியீடு என்றால் என்னவென்று தெரியாமல் இருக்கலாம், ஆனால் அவர்கள் அதன் விளைவுகளை உணர்வார்கள். அவர்கள் அதை ஒரு UI-இன் துரிதமான பதிலில், தரவின் விரைவான ஏற்றுதலில், மற்றும் அழகாக அளவிடக்கூடிய ஒரு செயலியின் மென்மையான செயல்பாட்டில் உணர்கிறார்கள். இன்றைய போட்டி டிஜிட்டல் நிலப்பரப்பில், செயல்திறன் என்பது ஒரு தொழில்நுட்ப விவரம் மட்டுமல்ல - இது ஒரு முக்கியமான அம்சம். டேட்டா ஸ்ட்ரக்சர்களில் தேர்ச்சி பெறுவதன் மூலம், நீங்கள் குறியீட்டை மேம்படுத்துவது மட்டுமல்ல; உலகளாவிய பார்வையாளர்களுக்காக சிறந்த, வேகமான மற்றும் நம்பகமான அனுபவங்களை நீங்கள் உருவாக்குகிறீர்கள்.