Hashing হল একটি প্রক্রিয়া যা একটি ইনপুট ডেটাকে একটি নির্দিষ্ট আকারের হ্যাশ কোডে রূপান্তরিত করে। এটি সাধারণত ডেটা দ্রুত অনুসন্ধান, সঞ্চয় এবং অ্যাক্সেস করার জন্য ব্যবহৃত হয়। হ্যাশিং একটি ডেটা স্ট্রাকচার তৈরি করতে সহায়ক, যা হ্যাশ টেবিল নামে পরিচিত। এই পদ্ধতি ডেটাকে একটি নির্দিষ্ট পদ্ধতিতে সঞ্চয় করতে সহায়ক এবং দ্রুত খোঁজার সুযোগ দেয়।
১. হ্যাশ টেবিলের ধারণা
হ্যাশ টেবিল হল একটি ডেটা স্ট্রাকচার যা কী-ভ্যালু জোড়ার মাধ্যমে ডেটা সঞ্চয় করে। এতে একটি হ্যাশ ফাংশন ব্যবহৃত হয় যা কী (key) থেকে একটি হ্যাশ ইনডেক্স তৈরি করে এবং সেই ইনডেক্স ব্যবহার করে সংশ্লিষ্ট ভ্যালুকে অ্যাক্সেস করা হয়।
১.১ হ্যাশ ফাংশন
হ্যাশ ফাংশন একটি ফাংশন যা ইনপুট হিসেবে কী নেয় এবং একটি নির্দিষ্ট দৈর্ঘ্যের হ্যাশ কোড বা ইনডেক্স রিটার্ন করে। একটি ভাল হ্যাশ ফাংশন সঠিকভাবে কাজ করে এবং হ্যাশ টেবিলে সংঘর্ষ (collision) কমাতে সাহায্য করে।
১.২ সংঘর্ষ (Collision)
সংঘর্ষ ঘটে যখন দুইটি আলাদা কী একই হ্যাশ ইনডেক্স তৈরি করে। সংঘর্ষের ক্ষেত্রে, হ্যাশ টেবিলের মধ্যে ডেটা সঞ্চয়ের জন্য একটি পদ্ধতি থাকতে হবে।
Hashing হল একটি প্রক্রিয়া যা ডেটাকে একটি নির্দিষ্ট আকারের হ্যাশ কোডে রূপান্তরিত করে। এটি ডেটা দ্রুত অনুসন্ধান, সঞ্চয় এবং অ্যাক্সেস করার জন্য ব্যবহৃত হয়। hashing মূলত ডেটা স্ট্রাকচার তৈরির জন্য ব্যবহৃত হয়, যা হ্যাশ টেবিল নামে পরিচিত।
১. হ্যাশ ফাংশন
হ্যাশ ফাংশন হল একটি অ্যালগরিদম যা একটি ইনপুট কী (key) থেকে একটি হ্যাশ কোড উৎপন্ন করে। এই হ্যাশ কোডটি একটি সংখ্যা বা সূচক হিসেবে কাজ করে, যা ইনপুট কী দ্বারা প্রদত্ত মানের অবস্থান নির্দেশ করে।
১.১ হ্যাশ ফাংশনের কাজ
- প্রবেশাধিকার: হ্যাশ ফাংশন একটি কী থেকে একটি নির্দিষ্ট আকারের হ্যাশ কোড তৈরি করে, যা ডেটা দ্রুত অ্যাক্সেস করতে সহায়ক।
- সমান বিতরণ: একটি ভাল হ্যাশ ফাংশন কীগুলিকে সঠিকভাবে বিতরণ করে, যাতে একই হ্যাশ কোড পাওয়ার সম্ভাবনা কম হয়।
১.২ হ্যাশ ফাংশনের উদাহরণ
unsigned int hash(const char *key) {
unsigned int hash = 0;
while (*key) {
hash = (hash << 5) + *key++; // Shift left and add current character
}
return hash % TABLE_SIZE; // Return index
}
২. হ্যাশ টেবিল
হ্যাশ টেবিল হল একটি ডেটা স্ট্রাকচার যা কী-ভ্যালু জোড়া ধারণ করে। হ্যাশ টেবিলের মাধ্যমে, ডেটাকে একটি ইনডেক্সে সংরক্ষণ করা হয়, যা হ্যাশ ফাংশনের মাধ্যমে তৈরি হয়।
২.১ হ্যাশ টেবিলের গঠন
- কী (Key): একটি ইউনিক শনাক্তকারী যা মানের সাথে যুক্ত থাকে।
- মান (Value): কী দ্বারা সংরক্ষিত তথ্য।
২.২ সংঘর্ষ (Collision)
সংঘর্ষ ঘটে যখন দুটি ভিন্ন কী একই হ্যাশ কোড তৈরি করে। সংঘর্ষ মোকাবেলা করার জন্য বিভিন্ন পদ্ধতি রয়েছে, যেমন:
- চেইনিং: প্রতিটি ইনডেক্সে একটি লিঙ্কড লিস্ট তৈরি করা, যাতে একাধিক কী একই ইনডেক্সে সংরক্ষিত হতে পারে।
- অ্যাড্রেসিং: হ্যাশ টেবিলে উপস্থিত অব্যবহৃত ইনডেক্সে কী সন্নিবেশ করা।
৩. হ্যাশিং এর সুবিধা
- দ্রুত অনুসন্ধান: হ্যাশিং ব্যবহার করে, ডেটা দ্রুত অনুসন্ধান করা যায়, সাধারণত O(1) সময় জটিলতায়।
- সংরক্ষণের সুবিধা: কী-ভ্যালু জোড়া ব্যবহার করে ডেটা সঞ্চয় এবং অ্যাক্সেস করা সহজ হয়।
- বিপুল ডেটা: বড় ডেটা সেটের মধ্যে দ্রুত তথ্য খোঁজার জন্য কার্যকরী।
৪. হ্যাশিং এর অসুবিধা
- সংঘর্ষের সমস্যা: সংঘর্ষ ঘটলে এটি কার্যকারিতা কমাতে পারে, এবং সঠিকভাবে মোকাবেলা করা জরুরি।
- স্থান ব্যবস্থাপনা: বড় ডেটা সেটের জন্য, হ্যাশ টেবিলের আকার বাড়ানো প্রয়োজন হতে পারে, যা কার্যকারিতা হ্রাস করে।
Hash Table একটি ডেটা স্ট্রাকচার যা কী-ভ্যালু জোড়া ধারণ করে এবং এটি দ্রুত অনুসন্ধান, সঞ্চয় এবং অ্যাক্সেস করার জন্য ব্যবহৃত হয়। একটি হ্যাশ টেবিল একটি হ্যাশ ফাংশন ব্যবহার করে কী থেকে একটি ইনডেক্স তৈরি করে, যা ডেটা স্টোর করার অবস্থান নির্দেশ করে। তবে, যখন দুটি ভিন্ন কী একই হ্যাশ ইনডেক্স তৈরি করে তখন সংঘর্ষ (collision) ঘটে। এই সমস্যা সমাধানের জন্য বিভিন্ন কৌশল রয়েছে, যার মধ্যে Chaining এবং Open Addressing সবচেয়ে সাধারণ।
১. Hash Table
১.১ Hash Table এর গঠন
- কী (Key): একটি ইউনিক শনাক্তকারী যা মানের সাথে যুক্ত থাকে।
- মান (Value): কী দ্বারা সঞ্চিত তথ্য।
- হ্যাশ ফাংশন: কী থেকে ইনডেক্স তৈরি করে, যা হ্যাশ টেবিলে ডেটার অবস্থান নির্দেশ করে।
১.২ হ্যাশ ফাংশন উদাহরণ
unsigned int hash(const char *key) {
unsigned int hash = 0;
while (*key) {
hash = (hash << 5) + *key++; // Shift left and add current character
}
return hash % TABLE_SIZE; // Return index
}
২. Collision Handling Techniques
২.১ Chaining
Chaining হল একটি পদ্ধতি যেখানে প্রতিটি ইনডেক্স একটি লিঙ্কড লিস্ট ধারণ করে। যখন দুটি কী একই হ্যাশ ইনডেক্সে পৌঁছে, তখন তারা একই লিস্টের মধ্যে সঞ্চয় হয়। এটি সংঘর্ষ মোকাবেলার একটি সহজ এবং কার্যকর পদ্ধতি।
২.১.১ Chaining এর সুবিধা
- সহজে বাস্তবায়নযোগ্য।
- ডেটা সঞ্চয় করতে অনেক স্থান পাওয়া যায়।
- একটি ইনডেক্সে একাধিক কী সঞ্চয় করা যায়।
২.১.২ C প্রোগ্রামে Chaining উদাহরণ
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TABLE_SIZE 10
// Node structure for linked list
typedef struct Node {
char *key;
int value;
struct Node *next;
} Node;
// Hash table structure
typedef struct HashTable {
Node **table;
} HashTable;
// Hash function
unsigned int hash(const char *key) {
unsigned int hash = 0;
while (*key) {
hash = (hash << 5) + *key++;
}
return hash % TABLE_SIZE;
}
// Create hash table
HashTable *createHashTable() {
HashTable *ht = malloc(sizeof(HashTable));
ht->table = malloc(sizeof(Node *) * TABLE_SIZE);
for (int i = 0; i < TABLE_SIZE; i++) {
ht->table[i] = NULL;
}
return ht;
}
// Insert key-value pair
void insert(HashTable *ht, const char *key, int value) {
unsigned int index = hash(key);
Node *newNode = malloc(sizeof(Node));
newNode->key = strdup(key);
newNode->value = value;
newNode->next = ht->table[index];
ht->table[index] = newNode;
}
// Search for a value by key
int search(HashTable *ht, const char *key) {
unsigned int index = hash(key);
Node *current = ht->table[index];
while (current != NULL) {
if (strcmp(current->key, key) == 0) {
return current->value;
}
current = current->next;
}
return -1; // Not found
}
// Free the hash table
void freeHashTable(HashTable *ht) {
for (int i = 0; i < TABLE_SIZE; i++) {
Node *current = ht->table[i];
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp->key);
free(temp);
}
}
free(ht->table);
free(ht);
}
int main() {
HashTable *ht = createHashTable();
insert(ht, "apple", 10);
insert(ht, "banana", 20);
insert(ht, "orange", 30);
printf("Value for 'apple': %d\n", search(ht, "apple")); // Output: 10
printf("Value for 'banana': %d\n", search(ht, "banana")); // Output: 20
printf("Value for 'grape': %d\n", search(ht, "grape")); // Output: -1 (not found)
freeHashTable(ht);
return 0;
}
২.২ Open Addressing
Open Addressing হল একটি পদ্ধতি যেখানে সংঘর্ষের সময় কী-ভ্যালু জোড়াগুলিকে হ্যাশ টেবিলের অন্যান্য খালি ইনডেক্সে সঞ্চয় করা হয়। সংঘর্ষ ঘটলে, অন্য ইনডেক্স অনুসন্ধান করা হয় এবং সেখানে নতুন কী সন্নিবেশ করা হয়।
২.২.১ Open Addressing এর উপ-প্রকার
- Linear Probing: পরবর্তী খালি ইনডেক্সে সন্নিবেশ।
- Quadratic Probing: ইনডেক্সের মধ্যে কোয়াড্রাটিক প্রগতিতে সন্নিবেশ।
- Double Hashing: দ্বিতীয় হ্যাশ ফাংশন ব্যবহার করে পরবর্তী ইনডেক্স নির্ধারণ।
২.২.২ C প্রোগ্রামে Open Addressing উদাহরণ (Linear Probing)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TABLE_SIZE 10
typedef struct HashTable {
char *keys[TABLE_SIZE];
int values[TABLE_SIZE];
} HashTable;
// Hash function
unsigned int hash(const char *key) {
unsigned int hash = 0;
while (*key) {
hash = (hash << 5) + *key++;
}
return hash % TABLE_SIZE;
}
// Create hash table
HashTable *createHashTable() {
HashTable *ht = malloc(sizeof(HashTable));
for (int i = 0; i < TABLE_SIZE; i++) {
ht->keys[i] = NULL; // Initialize keys to NULL
}
return ht;
}
// Insert key-value pair
void insert(HashTable *ht, const char *key, int value) {
unsigned int index = hash(key);
while (ht->keys[index] != NULL) {
// Linear probing
index = (index + 1) % TABLE_SIZE; // Move to the next index
}
ht->keys[index] = strdup(key);
ht->values[index] = value;
}
// Search for a value by key
int search(HashTable *ht, const char *key) {
unsigned int index = hash(key);
while (ht->keys[index] != NULL) {
if (strcmp(ht->keys[index], key) == 0) {
return ht->values[index]; // Return value if found
}
index = (index + 1) % TABLE_SIZE; // Move to the next index
}
return -1; // Not found
}
// Free the hash table
void freeHashTable(HashTable *ht) {
for (int i = 0; i < TABLE_SIZE; i++) {
free(ht->keys[i]);
}
free(ht);
}
int main() {
HashTable *ht = createHashTable();
insert(ht, "apple", 10);
insert(ht, "banana", 20);
insert(ht, "orange", 30);
printf("Value for 'apple': %d\n", search(ht, "apple")); // Output: 10
printf("Value for 'banana': %d\n", search(ht, "banana")); // Output: 20
printf("Value for 'grape': %d\n", search(ht, "grape")); // Output: -1 (not found)
freeHashTable(ht);
return 0;
}
৩. Collision Handling Techniques এর তুলনা
| বৈশিষ্ট্য | Chaining | Open Addressing |
|---|---|---|
| ডেটা স্ট্রাকচার | লিঙ্কড লিস্ট | টেবিলের মধ্যে সরাসরি ইনডেক্স |
| সংঘর্ষের স্থান | নতুন নোড যুক্ত করা হয় | অন্য খালি ইনডেক্সে সন্নিবেশ |
| স্পেস জটিলতা | O(n) (বড় লোডের জন্য) | O(1) (স্থানের ব্যবহার) |
| বিপরীত সংস্থান | সহজ এবং অস্থায়ী | সংঘর্ষ কমাতে কঠিন |
| পুনরায় সন্নিবেশ | সহজ | আরও জটিল |
Hash Functions হল এমন অ্যালগরিদম যা একটি ইনপুট ডেটাকে একটি নির্দিষ্ট দৈর্ঘ্যের হ্যাশ কোডে রূপান্তর করে। এই হ্যাশ কোডটি সাধারণত একটি সংখ্যা বা একটি অ্যালফানিউমেরিক স্ট্রিং, যা ডেটার অবস্থান নির্দেশ করতে ব্যবহৃত হয়। হ্যাশ ফাংশনগুলি ডেটা স্ট্রাকচারে ডেটাকে দ্রুত এবং কার্যকরভাবে সঞ্চয় ও খোঁজার জন্য অপরিহার্য।
১. Hash Functions এর মৌলিক ধারণা
১.১ Hash Functions এর বৈশিষ্ট্য
- নির্ধারিত আকার: যেকোনো আকারের ইনপুট ডেটা থেকে একটি নির্দিষ্ট দৈর্ঘ্যের আউটপুট তৈরি করে।
- দ্রুত: হ্যাশ ফাংশনগুলি সাধারণত দ্রুত হতে হয়, যাতে এটি দ্রুতভাবে ইনপুট প্রক্রিয়া করতে পারে।
- এবং বিপরীতযোগ্য নয়: একটি ভাল হ্যাশ ফাংশন থেকে আউটপুটকে মূল ইনপুট ডেটায় ফিরিয়ে আনা সম্ভব নয়।
- সংঘর্ষের প্রতিরোধ: দুটি ভিন্ন ইনপুটের জন্য একই হ্যাশ আউটপুট উৎপন্ন হওয়ার সম্ভাবনা কম হওয়া উচিত।
১.২ Hash Functions এর উদাহরণ
একটি সাধারণ হ্যাশ ফাংশন যা একটি স্ট্রিং থেকে একটি সংখ্যায় রূপান্তরিত করে:
unsigned int simpleHash(const char *key) {
unsigned int hash = 0;
while (*key) {
hash = (hash << 5) + *key++; // Shift left and add the character
}
return hash; // Return the computed hash
}
২. Hash Functions এর ব্যবহার
২.১ ডেটাবেসে
Hash Functions ডেটাবেসে দ্রুত অনুসন্ধান এবং সঞ্চয়ের জন্য ব্যবহৃত হয়। কী-ভ্যালু জোড়া ব্যবহার করে ডেটাকে হ্যাশ টেবিলে সঞ্চয় করা হয়, যা দ্রুত অ্যাক্সেস করার সুযোগ দেয়।
২.২ ক্রিপ্টোগ্রাফিতে
Hash Functions ক্রিপ্টোগ্রাফিতে নিরাপত্তা নিশ্চিত করার জন্য ব্যবহৃত হয়। উদাহরণস্বরূপ, পাসওয়ার্ড সুরক্ষায়, পাসওয়ার্ডগুলো হ্যাশ করা হয় এবং সিস্টেমে শুধুমাত্র হ্যাশ মান সঞ্চয় করা হয়। এতে মূল পাসওয়ার্ড প্রকাশ পায় না।
২.৩ ডেটা ইন্টেগ্রিটি
হ্যাশ ফাংশনগুলি ডেটার অখণ্ডতা পরীক্ষা করতে ব্যবহৃত হয়। যদি কোনো ডেটা পরিবর্তিত হয়, তবে তার হ্যাশ মানও পরিবর্তিত হবে। তাই, মূল এবং গুণগত মানের মধ্যে তুলনা করে ডেটা পরিবর্তন হয়েছে কিনা তা নিশ্চিত করা যায়।
২.৪ হ্যাশ টেবিল
Hash Functions হ্যাশ টেবিলে কী-ভ্যালু জোড়া সংরক্ষণ করার জন্য ব্যবহৃত হয়। ডেটাকে দ্রুত খোঁজার জন্য কী থেকে হ্যাশ ইনডেক্স তৈরি করা হয়।
২.৫ নেটওয়ার্কিং
নেটওয়ার্ক প্রোটোকলে ডেটা প্যাকেটের সংক্রমণ সময় পরিবর্তনের জন্য হ্যাশ ফাংশনগুলি ব্যবহৃত হয়, যাতে ডেটার অখণ্ডতা নিশ্চিত হয় এবং ডুপ্লিকেট প্যাকেট শনাক্ত করা যায়।
৩. Hash Functions এর উদাহরণ
৩.১ সাধারণ ব্যবহার
- SHA-256: নিরাপত্তার জন্য ব্যবহৃত একটি ক্রিপ্টোগ্রাফিক হ্যাশ ফাংশন।
- MD5: ডেটার অখণ্ডতা নিশ্চিত করার জন্য ব্যবহৃত হয়, যদিও এটি বর্তমানে নিরাপদ নয়।
৩.২ C প্রোগ্রামে Hash Function উদাহরণ (SHA-256)
SHA-256 ব্যবহার করতে হলে openssl লাইব্রেরি ব্যবহার করতে হয়। এখানে একটি উদাহরণ দেওয়া হল:
#include <stdio.h>
#include <openssl/sha.h>
int main() {
unsigned char hash[SHA256_DIGEST_LENGTH];
const char *string = "Hello, World!";
SHA256((unsigned char*)string, strlen(string), hash);
printf("SHA-256 hash: ");
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
printf("%02x", hash[i]);
}
printf("\n");
return 0;
}
৪. উপসংহার
Hash Functions ডেটা সঞ্চয়, অনুসন্ধান এবং নিরাপত্তার জন্য অপরিহার্য। এগুলি দ্রুত এবং কার্যকরী, যা সঠিকভাবে ডিজাইন করা হলে নিরাপদও হতে পারে। হ্যাশ ফাংশনগুলির সঠিক ব্যবহার ডেটার অখণ্ডতা, নিরাপত্তা এবং কার্যকারিতা নিশ্চিত করে।
Hashing একটি শক্তিশালী কৌশল যা বিভিন্ন ক্ষেত্র এবং পরিস্থিতিতে ব্যাপকভাবে ব্যবহৃত হয়। এটি ডেটাকে দ্রুত অনুসন্ধান, সঞ্চয় এবং নিরাপদে পরিচালনা করার জন্য অত্যন্ত কার্যকরী।
১. Hashing এর প্রয়োগ
১.১ ডেটাবেস সিস্টেম
Hashing ডেটাবেসে দ্রুত ডেটা খোঁজার জন্য ব্যবহৃত হয়। হ্যাশ টেবিলের মাধ্যমে, কী-ভ্যালু জোড়া দ্রুত অ্যাক্সেস করা যায়। যখন ইনপুট একটি কী হয়, তখন হ্যাশ ফাংশন ব্যবহার করে ইনডেক্স তৈরি করা হয় এবং সেই ইনডেক্স ব্যবহার করে সংশ্লিষ্ট ভ্যালুকে খোঁজা হয়।
১.২ ক্রিপ্টোগ্রাফি
Hashing নিরাপত্তার জন্য গুরুত্বপূর্ণ। পাসওয়ার্ড, টোকেন এবং অন্যান্য সংবেদনশীল তথ্য হ্যাশ করে সঞ্চয় করা হয়, যা মূল তথ্যকে সুরক্ষিত রাখে। এই প্রক্রিয়া নিশ্চিত করে যে পাসওয়ার্ড বা তথ্যগুলি সরাসরি অ্যাক্সেসযোগ্য নয়।
১.৩ ডেটা ইন্টেগ্রিটি
হ্যাশিং ডেটার অখণ্ডতা নিশ্চিত করতে ব্যবহৃত হয়। কোনো তথ্য পরিবর্তিত হলে তার হ্যাশ মানও পরিবর্তিত হয়। তাই, মূল এবং গুণগত মানের মধ্যে তুলনা করে ডেটা পরিবর্তন হয়েছে কিনা তা নিশ্চিত করা যায়।
১.৪ নেটওয়ার্কিং
নেটওয়ার্ক প্রোটোকলে ডেটা প্যাকেটের সংক্রমণের সময় হ্যাশ ফাংশনগুলি ব্যবহার করা হয়, যাতে ডেটার অখণ্ডতা নিশ্চিত হয় এবং ডুপ্লিকেট প্যাকেট শনাক্ত করা যায়।
১.৫ ক্যাশিং
হ্যাশিং ক্যাশিং সিস্টেমে ডেটা দ্রুত খুঁজে পাওয়ার জন্য ব্যবহৃত হয়। এতে ডেটার একটি হ্যাশ মান তৈরি করা হয় এবং সেটি ক্যাশে সঞ্চয় করা হয়। পরবর্তী সময়ে একই তথ্যের জন্য হ্যাশ মানটি ব্যবহার করে দ্রুত অ্যাক্সেস করা যায়।
২. বাস্তব জীবনের উদাহরণ
২.১ পাসওয়ার্ড ম্যানেজার
পাসওয়ার্ড ম্যানেজারগুলি ব্যবহারকারীদের পাসওয়ার্ড সুরক্ষিত রাখতে হ্যাশিং ব্যবহার করে। যখন ব্যবহারকারী একটি নতুন পাসওয়ার্ড তৈরি করে, তখন এটি হ্যাশ করা হয় এবং শুধুমাত্র হ্যাশ মানটি সিস্টেমে সঞ্চয় করা হয়। এটি নিশ্চিত করে যে মূল পাসওয়ার্ড কখনোই প্রকাশিত হয় না।
২.২ ডিজিটাল স্বাক্ষর
ডিজিটাল স্বাক্ষরে, একটি নথির হ্যাশ মান তৈরি করা হয় এবং এটি স্বাক্ষর করার জন্য ব্যবহৃত হয়। এই প্রক্রিয়া নিশ্চিত করে যে নথিটি পরিবর্তন করা হয়নি এবং স্বাক্ষরকারী সত্যিই নথিটি স্বাক্ষর করেছেন।
২.৩ ফাইল ইন্টেগ্রিটি চেক
ফাইলের হ্যাশ মান তৈরি করা হয় এবং এটি পরে সংরক্ষণ করা হয়। যখন ফাইলটি পরবর্তীতে চেক করা হয়, তখন তার হ্যাশ মান আবার গণনা করা হয়। যদি উভয় হ্যাশ মান একই না হয়, তবে এটি নির্দেশ করে যে ফাইলটি পরিবর্তিত হয়েছে।
২.৪ অনলাইন শপিং
অনলাইন শপিং সাইটে ব্যবহারকারীদের ক্রয়ের সময় ডেটা সুরক্ষার জন্য হ্যাশিং ব্যবহার করা হয়। ক্রেডিট কার্ড তথ্য এবং অন্যান্য সংবেদনশীল তথ্য হ্যাশ করা হয় যাতে তা সুরক্ষিত থাকে।
২.৫ ব্লকচেইন
ব্লকচেইন প্রযুক্তিতে প্রতিটি ব্লক একটি হ্যাশ ফাংশন দ্বারা প্রাপ্ত হ্যাশ কোড ধারণ করে। এটি নিশ্চিত করে যে ব্লকের তথ্য পরিবর্তন করা হলে পরবর্তী ব্লকের হ্যাশ কোডও পরিবর্তিত হবে, ফলে পুরো চেইন পরিবর্তিত হয়।
Read more