rong bà i viết nà y, tôi sẽ giá»›i thiệu vá»›i các bạn vá» cách láºp trình vá»›i con trá» (pointer) trong việc cấp phát bá»™ nhá»› động (dynamic memory alocation) bằng ngôn ngữ C++. Äối vá»›i các bạn đã có kinh nghiệm láºp trình vá»›i C++ thì bà i nà y đối vá»›i các bạn chỉ là "a-bá»-cá»" mà thôi. Nhưng vá»›i các bạn má»›i há»c C++ thì có lẽ là bổ Ãch.
Nếu bạn má»›i há»c láºp trình và là m quen vá»›i cấu trúc dữ liệu thì má»™t trong số những cấu trúc dữ liệu đầu tiên mà bạn "rá»›" tá»›i là Stack (ngăn xếp) và Queue (hà ng đợi). Bạn có thể dùng 1 mảng (array) để thiết kế Stack và Queue. Dùng mảng thì đơn giản, nhưng bạn sẽ gặp má»™t số bất lợi như sau:
*
Lãng phà bá»™ nhá»›: giả sá» bạn khai báo int array_entry[100] thì bạn sẽ có 1 vùng nhá»› cho 100 phần tá», nhưng nếu chương trình cá»§a bạn chỉ thưá»ng xuyên dùng có 10 phần tá», và 1 và i lần là dùng đến 100 phần tá» thì tức là bạn đã phà phạm 90 phần tá».
*
Thiếu bá»™ nhá»›: vì tiết kiệm, bạn chỉ khai báo int array_entry[10], nhưng nếu bạn cần dùng đến 15 phần tá» thì...overflow ngay. Chưa hết, array cần má»™t vùng nhá»› liên tục, giả sá» máy bạn vẫn còn nhiá»u bá»™ nhá»› trống, nhưng không có vùng nhá»› trống liên tục nà o đủ lá»›n cho mảng cá»§a bạn. Thế là vẫn...thiếu bá»™ nhá»›.
*
Và cuối cùng, ngưá»i ta khi thấy bạn viết như váºy thì coi bạn là dân amateur, buồn nhỉ? L
Nhưng không sao, bà i viết nà y sẽ giúp bạn vượt qua các trở ngại đó. Bạn sẽ biết cách ứng dụng con trỠđể tạo thà nh các cấu trúc dữ liệu kiên kết (linked structure) để tạo thà nh các linked stack hoặc linked queue. Bạn sẽ biết được cách toà n quyá»n cấp phát bá»™ nhá»› khi có nhu cầu sá» dụng; và khi không dùng nữa thì ta xoá nó Ä‘i, nhưá»ng memory cho các chương trình khác.
Ghi chú: xem như là bạn đã có há»c và biết qua sÆ¡ sÆ¡ vá» C++ rồi, nhứng Ä‘oạn code trong bà i viết nà y là C++ chứ không phải là C.
Ứng dụng con trá», ta có thể tạo ra má»™t danh sách liên kết (mảng liên kết - linked list) như sau:
Phần đánh dấu mà u hồng (và nút tròn đầu tiên) là các con trá», có nhiệm vụ link đến phần tá» tiếp theo trong danh sách. Nhá» có các link nà y mà khi Ä‘ang ở phần tá» thứ nhất, bạn sẽ có manh mối để lần đến phần tá» thứ hai, rồi phần tá» thứ ba...
Má»™t phần tá» cá»§a danh sách có thể được biểu diá»…n qua cấu trúc như sau (1 phần tá» ta gá»i là 1 Node):
struct Node {
// data members
Node_entry entry;
Node *next;
//constructors
Node();
Node(Node_entry item, Node *add_on = NULL);
};
Ghi chú: Node_entry là kiểu dữ liệu để chứa data cá»§a phần tá», entry chÃnh là nÆ¡i data cá»§a phần tỠđược lưu. Ở và dụ trong hình trên, vá»›i node đầu tiên thì entry sẽ chứa Fred, 367-2205 và Jan. 28.
Và ta có các hà m khởi tạo cho nó như sau:
Node::Node()
{
next = NULL;
}
Node::Node(Node_entry item, Node *add_on)
{
entry = item;
next = add_on;
}
Như váºy, khi ta khai báo Node* data và khởi tạo xong cho data thì data->entry sẽ là phần dữ liệu cá»§a node đó, và data->next sẽ là đưá»ng dẫn tá»›i node tiếp theo. Như thế thì ta có thể duyệt hết toà n bá»™ data mà ta đã lưu trong danh sách rồi. Äể rõ hÆ¡n, ta hãy xem má»™t và dụ qua Ä‘oạn code nhá» sau. Chú ý: khi data->next == NULL thì tức là node nà y là phần tá» cuối cùng.
Äoạn code trong và dụ sẽ tạo ra má»™t danh sách liên kết như trong hình trên (không tin thì bạn...thá» xem là biết liá»n J). Äịa chỉ bá»™ nhá»› cá»§a các node thì hoà n toà n ngẫu nhiên và không liên tục vì nó là dynamic memory allocation mà .
Thế là đã Ok cho việc tạo một cấu trúc liên kết. GiỠta bắt tay và o xây dựng Linked Stack và Linked Queue. Tôi sẽ trình bà y phần Linked Stack thôi, phần Linked Queue thì các bạn hãy phát triển thêm nhé. Cũng hoà n toà n tương tự thôi.
Ta khai báo Stack như sau:
enum Error_code {underflow, success, overflow};
typedef int Stack_entry;
class Stack {
public:
Stack();
Bool empty() const;
Stack_entry push(const Stack_entry &item);
Stack_entry top(Stack_entry &item) const;
Error_code pop();
protected:
Node *top_node;
}
Sau đó là các đoạn code cho các hà m trong Stack như sau:
Stack_entry Stack::push(const Stack_entry &item)
{
Node *new_top = new Node(item, top_node);
if (new_top == NULL) return 0;
top_node = new_top;
return item;
}
/************************************************** ******************/
Error_code Stack::pop()
{
Node *old_top = top_node;
if (top_node == NULL) return underflow;
top_node = old_top->next ;
delete old_top;
count--;
return success;
}
/************************************************** *****************/
Stack_entry Stack::top(Stack_entry &item) const
{
if (top_node == NULL) return 0;
item = top_node->entry;
return item;
}
/************************************************** *****************/
bool Stack::empty() const
{
if (top_node == NULL) return true;
return false;
}
/************************************************** *****************/
Stack::Stack()
{
top_node = NULL;
count = 0;
}
Như thế đó, ta đã có 1 Linked Stack mà không dùng array. Dữ liệu được nháºp và o tá»›i đâu thì bá»™ nhá»› được cấp phát tá»›i đó. Và khi dữ liệu được lấy ra khá»i stack thì phần bá»™ nhá»› cá»§a nó được giải phóng ngay láºp tức, để dà nh cho việc khác.