Mỗi phần tử được gọi là một node hay nút trong danh sách liênkết đơn là một cấu trúc có hai thành phần: - Thành phần dữ liệu: lưu thông tin về bản thân phần tử đó.. - Đặc điểm của danh s
Danh sách liên kết đơn là gì?
Khái niệm
Danh sách liên kết đơn (Single Linked List) là một cấu trúc dữ liệu động hiệu quả, trong đó mỗi phần tử (node hay nút) đều liên kết với phần tử tiếp theo trong danh sách Mỗi node trong danh sách liên kết đơn gồm hai thành phần chính: dữ liệu và con trỏ trỏ đến node kế tiếp Cấu trúc này giúp quản lý dữ liệu linh hoạt, dễ dàng thao tác chèn, xóa và truy xuất dữ liệu một cách tối ưu, phù hợp cho các ứng dụng đòi hỏi tính linh hoạt cao trong xử lý danh sách dữ liệu.
- Thành phần dữ liệu: lưu thông tin về bản thân phần tử đó.
- Thành phần liên kết: lưu địa chỉ phần tử đứng sau trong danh sách, nếu phần tử đó là phần tử cuối cùng thì thành phần này bằng NULL.
- Đặc điểm của danh sách liên kết đơn:
Danh sách liên kết đơn là một cấu trúc dữ liệu động được xây dựng dựa trên cơ chế cấp phát động, giúp tối ưu hiệu quả lưu trữ và thao tác dữ liệu Cấu trúc này gồm các nút đơn lẻ, mỗi nút chứa dữ liệu và một con trỏ trỏ tới nút tiếp theo, cho phép dễ dàng thêm, xóa phần tử Nhờ đặc điểm linh hoạt của nó, danh sách liên kết đơn thường được sử dụng trong các ứng dụng yêu cầu thao tác dữ liệu linh hoạt và hiệu quả Trong các bài toán cần quản lý danh sách dữ liệu biến đổi liên tục, danh sách liên kết đơn là một giải pháp tối ưu nhờ khả năng mở rộng và giảm thiểu bộ nhớ dư thừa.
- Được cấp phát bộ nhớ khi chạy chương trình
- Có thể thay đổi kích thước qua việc thêm, xóa phần tử
- Kích thước tối đa phụ thuộc vào bộ nhớ khả dụng của RAM
- Các phần tử được lưu trữ ngẫu nhiên (không liên tiếp) trong RAM
Và do tính liên kết của phần tử đầu và phần tử đứng sau nó trong danh sách liên kết đơn, nó có các đặc điểm sau:
- Chỉ cần nắm được phần tử đầu và cuối là có thể quản lý được danh sách
- Truy cập tới phần tử ngẫu nhiên phải duyệt từ đầu đến vị trí đó
- Chỉ có thể tìm kiếm tuyến tính một phần tử
Cách tạo danh sách liên kết đơn
Trong việc quản lý danh sách liên kết đơn, điều quan trọng là xác định thành phần chính gồm node, đồng thời cần biết phần tử đầu và phần tử cuối để dễ dàng kiểm soát danh sách Vì mỗi node đều liên kết với node kế tiếp, chỉ cần xác định vị trí của phần tử đầu và phần tử cuối là có thể quản lý toàn bộ danh sách một cách hiệu quả Do đó, việc tạo ra một cấu trúc dữ liệu lưu trữ địa chỉ của phần tử đầu (head) và phần tử cuối (tail) là bước cơ bản và cần thiết để tối ưu hóa quá trình thao tác với danh sách liên kết đơn.
Khi mới tạo danh sách liên kết, danh sách sẽ không có phần tử nào, do đó, các con trỏ head và tail không trỏ vào đâu cả, và ta sẽ gán chúng bằng NULL để xác định danh sách ban đầu rỗng Việc xây dựng hàm tạo danh sách giúp đảm bảo danh sách liên kết không chứa phần tử, phù hợp cho các thao tác thêm hoặc xóa phần tử sau này Đây là bước cần thiết để khởi tạo danh sách liên kết đúng cách, đảm bảo tính ổn định và dễ dàng trong xử lý các thao tác sau.
- Bây giờ để tạo một danh sách, ta làm như sau:
- CreateList(list); // Gán head và tail bằng NULL
Cấu trúc dữ liệu ngăn xếp (Stack )
Ngăn xếp (stack ) là gì ?
Ngăn xếp (Stack) là một cấu trúc dữ liệu trừu tượng (ADT) được sử dụng phổ biến trong hầu hết các ngôn ngữ lập trình Ngăn xếp hoạt động theo nguyên tắc LIFO (last in, first out), nghĩa là phần tử mới nhất được đưa vào sẽ là phần tử đầu tiên được lấy ra Tên gọi "ngăn xếp" phản ánh cách hoạt động giống như một chồng đĩa hoặc một cỗ bài trong đời sống hàng ngày.
Trong đời sống thực, ngăn xếp chỉ cho phép thao tác với phần tử trên cùng, như thêm hoặc lấy ra một lá bài hay một cái đĩa từ trên cùng của ngăn xếp Cấu trúc dữ liệu trừu tượng ngăn xếp mô phỏng nguyên tắc này, chỉ cho phép truy cập và thao tác tại vị trí trên cùng của ngăn xếp Điều này có nghĩa là tại bất kỳ thời điểm nào, chúng ta chỉ có thể tương tác với phần tử nằm trên đỉnh của ngăn xếp, đảm bảo tính thứ tự LIFO (Last In, First Out).
Ngăn xếp là cấu trúc dữ liệu dạng LIFO, viết tắt của Last-In-First-Out, nghĩa là phần tử được thêm vào cuối cùng sẽ được truy cập đầu tiên Trong ngăn xếp, hoạt động chèn phần tử được gọi là PUSH, còn hoạt động loại bỏ phần tử được gọi là POP, giúp quản lý dữ liệu một cách hiệu quả theo nguyên tắc LIFO.
Biểu diễn cấu trúc dữ liệu (Stack )
Dưới đây là sơ đồ minh họa một ngăn xếp và các hoạt động diễn ra trên ngăn xếp.
Ngăn xếp có thể được triển khai theo nhiều phương pháp như Mảng (Array), Cấu trúc (Struct), Con trỏ (Pointer), và Danh sách liên kết (Linked List) Ngăn xếp có thể có kích thước cố định hoặc linh hoạt thay đổi theo nhu cầu Trong bài viết này, chúng tôi sẽ trình bày cách triển khai ngăn xếp sử dụng mảng, cụ thể là các ngăn xếp cố định để giúp bạn hiểu rõ hơn về cấu trúc dữ liệu này.
Các hoạt động cơ bản trên cấu trúc dữ liệu ngăn xếp
Các hoạt động cơ bản trên ngăn xếp bao gồm khởi tạo, sử dụng và xóa ngăn xếp, giúp quản lý dữ liệu một cách hiệu quả Bên cạnh đó, một ngăn xếp còn có hai hoạt động nguyên sơ liên quan đến khái niệm: thao tác đẩy (push) và thao tácPop giúp thêm hoặc loại bỏ phần tử khỏi ngăn xếp Việc hiểu rõ các hoạt động này là nền tảng để sử dụng ngăn xếp trong các thuật toán và cấu trúc dữ liệu phức tạp hơn.
- Hoạt động push(): lưu giữ một phần tử trên ngăn xếp.
- Hoạt động pop(): xóa một phần tử từ ngăn xếp.
Khi dữ liệu đã được đẩy lên ngăn xếp, việc kiểm tra trạng thái của ngăn xếp trở nên quan trọng để sử dụng hiệu quả cấu trúc dữ liệu này Các tính năng hỗ trợ như kiểm tra xem ngăn xếp có còn phần tử hay không, hoặc xem phần tử ở đỉnh ngăn xếp giúp đảm bảo quá trình thao tác diễn ra chính xác và tối ưu hơn Điều này giúp người dùng quản lý dữ liệu trong ngăn xếp một cách hiệu quả, phù hợp với các yêu cầu của các ứng dụng lập trình.
- Hoạt động peek(): lấy phần tử dữ liệu ở trên cùng của ngăn xếp, mà không xóa phần tử này.
- Hoạt động isFull(): kiểm tra xem ngăn xếp đã đầy hay chưa.
- Hoạt động isEmpty(): kiểm tra xem ngăn xếp là trống hay không.
Trong mọi thời điểm, chúng ta duy trì một con trỏ gọi là top trỏ tới phần tử dữ liệu cuối cùng vừa được PUSH vào ngăn xếp Con trỏ top luôn biểu diễn vị trí của phần tử trên cùng, giúp dễ dàng truy cập giá trị của phần tử này mà không cần thực hiện hoạt động xóa (pop) Việc sử dụng con trỏ top là cách hiệu quả để quản lý và truy xuất dữ liệu trong ngăn xếp một cách nhanh chóng và chính xác.
Ứng dụng của ngăn xếp
Trong lập trình C/C++, xử lý gọi hàm đóng vai trò quan trọng trong việc tính giá trị biểu thức và xử lý ngắt trong hệ thống máy tính Các hàm này thường được sử dụng trong các chương trình biên dịch, trình duyệt web và trình soạn thảo văn bản để thực thi các thao tác phức tạp Trong việc định giá biểu thức, có các dạng chính như biểu thức trung tố, gồm toán tử hai ngôi nằm giữa hai toán hạng; biểu thức hậu tố, với toán tử đứng sau toán hạng; và biểu thức tiền tố, trong đó toán tử đứng trước toán hạng Những phương pháp này giúp tối ưu hóa việc xử lý các biểu thức toán học và lập trình hiệu quả hơn.
VD định giá biểu thức A = b + c * d /e – f Trung tố a*(b-c)/d Hậu tố abc-*d/Tiền tố /*a-bcd
Cấu trúc dữ liệu hàng đợi (Queue ) là gì?
Khái niệm
Hàng đợi (Queue) là một cấu trúc dữ liệu trừu tượng quan trọng trong lập trình, có đặc điểm chính là nguyên tắc FIFO (first in, first out) – vào trước ra trước Trong cấu trúc này, phần tử được thêm vào cuối cùng và luôn được xử lý theo thứ tự đã nhập, giúp đảm bảo sự công bằng và hiệu quả trong quản lý dữ liệu Chính nhờ đặc điểm này, hàng đợi thường được đặt tên dựa trên hình ảnh hàng người xếp hàng trong đời sống hàng ngày, dễ hiểu và dễ áp dụng trong các ứng dụng thực tế.
Khác với ngăn xếp, hàng đợi hoạt động mở ở cả hai đầu, với một đầu để chèn dữ liệu (sắp vào hàng) và đầu kia để xóa dữ liệu (rời hàng) Cấu trúc dữ liệu hàng đợi tuân theo phương pháp First-In-First-Out (FIFO), nghĩa là dữ liệu được nhập vào đầu tiên sẽ được truy cập và xử lý trước tiên Hàng đợi là cấu trúc dữ liệu quan trọng trong lập trình, giúp quản lý thứ tự xử lý các nhiệm vụ một cách hợp lý và hiệu quả.
Trong đời sống hàng ngày, chúng ta thường gặp các ví dụ về hàng đợi, như hàng xe ô tô trên đường một chiều khi tắc nghẽn, nơi xe vào trước sẽ ra khỏi đầu tiên theo nguyên tắc FIFO Ngoài ra, các ví dụ phổ biến khác bao gồm xếp hàng học sinh vào lớp, xếp hàng mua vé tại các sự kiện hoặc siêu thị, giúp đảm bảo công bằng và trật tự trong quá trình phân phối dịch vụ Các hình thức hàng đợi này minh họa rõ nét cách hoạt động của cấu trúc dữ liệu hàng đợi trong thực tế, góp phần nâng cao hiệu quả xử lý và tổ chức trong cuộc sống hàng ngày.
Biễu diễn của cấu trúc hàng đợi
Giờ thì bạn có thể hình dung rõ hơn về hàng đợi là gì, một cấu trúc dữ liệu cho phép truy cập cả hai đầu để thêm hoặc loại bỏ phần tử Hàng đợi hoạt động theo nguyên tắc FIFO (First In, First Out), nghĩa là phần tử đến trước sẽ được xử lý trước, giúp tối ưu hóa quá trình xử lý dữ liệu Dưới đây là biểu diễn của hàng đợi dưới dạng cấu trúc dữ liệu rõ ràng và dễ hiểu, phù hợp cho các ứng dụng trong lập trình và quản lý dữ liệu.
Hàng đợi là cấu trúc dữ liệu phổ biến có thể được triển khai bằng nhiều phương pháp như Mảng (Array), Danh sách liên kết (Linked List), Con trỏ (Pointer) và Cấu trúc (Struct) Để đơn giản, bài viết sẽ tập trung vào cách triển khai hàng đợi bằng mảng một chiều, giúp người đọc dễ hình dung và áp dụng vào thực tế.
Các hoạt động cơ bản trên cấu trúc hàng đợi
Các hoạt động chính trên cấu trúc dữ liệu hàng đợi bao gồm khởi tạo hàng đợi, thao tác sử dụng dữ liệu trong hàng đợi như thêm phần tử ( enqueue ) và lấy phần tử ( dequeue ), cũng như xóa dữ liệu khỏi bộ nhớ Các thao tác này giúp quản lý hiệu quả dữ liệu theo nguyên tắc FIFO ( First In, First Out ), đảm bảo thứ tự xử lý chính xác Hiểu rõ các hoạt động cơ bản này là nền tảng quan trọng để triển khai các ứng dụng sử dụng hàng đợi trong lập trình và công nghệ thông tin.
- Hoạt động enqueue(): thêm (hay lưu trữ) một phần tử vào trong hàng đợi.
Hoạt động dequeue() dùng để xóa một phần tử khỏi hàng đợi, giúp quản lý dữ liệu hiệu quả Để đảm bảo hoạt động của hàng đợi diễn ra trơn tru, việc kiểm tra trạng thái của hàng đợi là điều cần thiết Các tính năng hỗ trợ của hàng đợi còn bao gồm các phương thức kiểm tra xem hàng đợi có còn phần tử hay không, nhằm tối ưu hóa quá trình xử lý dữ liệu Việc sử dụng đúng cách các tính năng này sẽ giúp phát huy tối đa hiệu quả của cấu trúc dữ liệu hàng đợi trong các ứng dụng thực tế.
- Phương thức peek(): lấy phần tử ở đầu hàng đợi, mà không xóa phần tử
- này.Phương thức isFull(): kiểm tra xem hàng đợi là đầy hay không.
- Phương thức isEmpty(): kiểm tra xem hàng đợi là trống hay hay không.
Trong cấu trúc dữ liệu hàng đợi, quá trình dequeue (xóa) dữ liệu diễn ra tại vị trí được chỉ định bởi con trỏ front, đảm bảo các phần tử được loại bỏ theo thứ tự FIFO Đồng thời, quá trình enqueue (nhập) dữ liệu mới vào hàng đợi được thực hiện nhờ vào con trỏ rear, giúp duy trì tính chất hàng đợi một cách chính xác và hiệu quả.
Véc tơ trong C++ là gì?
Khái niệm
Vector trong C++ là một kiểu dữ liệu giống như mảng động (dynamic array), nhưng có khả năng tự động điều chỉnh kích thước khi thêm hoặc xóa phần tử dựa trên nhu cầu của tác vụ Khác với mảng thông thường chỉ lưu trữ một số giá trị cố định dưới một tên biến duy nhất, vector cho phép lưu trữ nhiều phần tử và tự chủ trong việc quản lý bộ nhớ Các phần tử của vector được lưu trữ trong bộ nhớ liên tiếp (contiguous storage), giúp việc truy cập và duyệt qua chúng trở nên nhanh chóng và hiệu quả thông qua sử dụng iterator.
Vì sao nên dùng véc tơ?
- Bạn không cần phải khai báo kích thước của mảng ví dụ int A[100]…, vì vector có thể tự động nâng kích thước lên.
- Nếu bạn thêm 1 phần tử vào vector đã đầy rồi, thì nó sẽ tự động tăng kích thước của nó lên để dành chỗ cho giá trị mới này.
- Vector còn giúp cho bạn biết số lượng các phần tử mà bạn đang lưu trong
- Dùng số phần tử âm vẫn được trong vector ví dụ A[-6], A[-9], rất tiện trongđó.việc cài đặt các giải thuật.
Véc tơ có thứ tự trong C++ không ?
Trong C++, không có vector nào không được sắp xếp hợp lý, giúp các phần tử trong vector nằm trong bộ nhớ liền kề để dễ dàng truy cập qua các iterator Dữ liệu trong vector thường được chèn vào cuối, việc này có thể mất thời gian biến thiên do phải mở rộng vector khi cần thiết Xóa phần tử cuối cùng trong vector diễn ra nhanh chóng, chỉ mất thời gian không đổi vì không ảnh hưởng đến kích thước Tuy nhiên, việc chèn hoặc xóa phần tử ở đầu hoặc giữa vector sẽ có độ phức tạp tuyến tính theo thời gian, ảnh hưởng đến hiệu suất khi xử lý lượng lớn dữ liệu.
Các hàm trong C++
1 push_back(): Hàm đẩy một phần tử vào vị trí sau cùng của vector Nếu kiểu của đối tượng được truyền dưới dạng tham số trong push_back() không giống với kiểu của vector thì sẽ bị ném ra. ten-vector.push_back(ten-cua-phan-tu);
2 assign(): Nó gán một giá trị mới cho các phần tử vector bằng cách thay thế các giá trị cũ. ten-vector.assign(int size, int value);
3 pop_back(): Hàm pop_back () được sử dụng để xóa đi phần tử cuối cùng một vector. ten-vector.pop_back();
4 insert(): Hàm này chèn các phần tử mới vào trước phần tử trước vị trí được trỏ bởi vòng lặp Chúng ta cũng có thể chuyển một số đối số thứ ba, đếm số lần phần tử được chèn vào trước vị trí được trỏ. ten-vector.insert(position, value);
5 erase(): Hàm được sử dụng để xóa các phần tử tùy theo vị trí vùng chứa ten-vector.erase(position); ten-vector.erase(start-position, end-position);
6 emplace(): Nó mở rộng vùng chứa bằng cách chèn phần tử mới vào ten-vector.emplace(ten-vector.position, element);
7 emplace_back(): Nó được sử dụng để chèn một phần tử mới vào vùng chứa vector, phần tử mới sẽ được thêm vào cuối vector ten-vector.emplace_back(value);
8 swap(): Hàm được sử dụng để hoán đổi nội dung của một vector này với một vector khác cùng kiểu Kích thước có thể khác nhau. ten-vector-1.swap(ten-vector-2);
9 clear(): Hàm được sử dụng để loại bỏ tất cả các phần tử của vùng chứa vector. ten-vector.clear();
Cấu trúc dữ liệu cây
Cấu trúc dữ liệu cây là gì?
Cây là cấu trúc dữ liệu biểu diễn các nút (node) được kết nối với nhau bởi các cạnh Trong phần này, chúng ta sẽ tìm hiểu về Cây nhị phân (Binary Tree) và Cây tìm kiếm nhị phân (Binary Search Tree), hai loại cây phổ biến trong lưu trữ và xử lý dữ liệu Cây nhị phân có cấu trúc mỗi nút tối đa hai con, giúp tối ưu hóa các thao tác truy xuất dữ liệu Cây tìm kiếm nhị phân còn có đặc điểm các nút con bên trái chứa giá trị nhỏ hơn, còn các nút bên phải chứa giá trị lớn hơn, hỗ trợ tìm kiếm và sắp xếp dữ liệu hiệu quả.
Cây nhị phân là một cấu trúc dữ liệu đặc biệt dùng để lưu trữ dữ liệu hiệu quả, trong đó mỗi nút có tối đa hai nút con Cây nhị phân tận dụng lợi thế của cả hai dạng cấu trúc dữ liệu: mảng đã sắp thứ tự và danh sách liên kết, giúp các thao tác tìm kiếm trở nên nhanh chóng như trong mảng đã sắp thứ tự Ngoài ra, việc chèn và xóa nút trong cây nhị phân cũng diễn ra nhanh chóng nhờ cấu trúc linh hoạt của danh sách liên kết Do đó, cây nhị phân là một giải pháp tối ưu cho các ứng dụng yêu cầu xử lý dữ liệu hiệu quả.
Các khái niệm cơ bản về cây nhị phân
- Đường: là một dãy các nút cùng với các cạnh của một cây.
Nút gốc (root) là nút trên cùng của cây và là điểm bắt đầu của toàn bộ cấu trúc cây Mỗi cây chỉ có một nút gốc duy nhất, từ đó phát xuất ra các đường dẫn tới các nút con khác trong cây Nút gốc không có bất kỳ nút cha nào, đóng vai trò quan trọng trong cấu trúc dữ liệu cây và giúp xác định hệ thống các kết nối trong cây một cách rõ ràng.
- Nút cha: bất kỳ nút nào ngoại trừ nút gốc mà có một cạnh hướng lên một nút khác thì được gọi là nút cha.
- Nút con: nút ở dưới một nút đã cho được kết nối bởi cạnh dưới của nó được gọi là nút con của nút đó.
- Nút lá: nút mà không có bất kỳ nút con nào thì được gọi là nút lá.
- Cây con: cây con biểu diễn các con của một nút.
- Truy cập: kiểm tra giá trị của một nút khi điều khiển là đang trên một nút đó.
- Duyệt: duyệt qua các nút theo một thứ tự nào đó.
Trong lý thuyết cây, bậc của một nút thể hiện số con của nút đó Nếu nút gốc có bậc bằng 0, thì các nút con của nó sẽ có bậc lần lượt là 1, 2, và cứ tiếp tục như vậy đối với các nút cháu Bậc của nút giúp xác định cấu trúc phân cấp của cây và có vai trò quan trọng trong việc phân tích các đặc điểm của dữ liệu cây Hiểu rõ về bậc của nút là kiến thức cơ bản để xây dựng và tối ưu hóa các cây dữ liệu trong các thuật toán trò chơi và hệ thống xử lý dữ liệu.
- Khóa (Key): biểu diễn một giá trị của một nút dựa trên những gì mà một thao tác tìm kiếm thực hiện trên nút.
Biễu diễn cây tìm kiếm nhị phân
Cây tìm kiếm nhị phân biểu diễn một hành vi đặc biệt trong cấu trúc dữ liệu, trong đó mỗi nút có quy tắc rõ ràng về giá trị của các nút con trái và phải Cụ thể, con bên trái của một nút phải có giá trị nhỏ hơn giá trị của nút cha, còn con bên phải của một nút phải có giá trị lớn hơn giá trị của nút cha Mô hình này giúp duy trì tính chất sắp xếp của dữ liệu, tối ưu cho các thao tác tìm kiếm, chèn và xóa trong cây Hình minh họa rõ ràng giúp hình dung cách các nút trong cây tìm kiếm nhị phân duy trì mối quan hệ so sánh chặt chẽ nhau dựa trên giá trị.
- Chúng ta đang triển khai cây bởi sử dụng đối tượng nút và kết nối chúng thông qua các tham chiếu.
Hoạt động cơ bản trên cây tìm kiếm nhị phân
- Chèn: chèn một phần tử vào trong một cây/ tạo một cây.
- Tìm kiếm: tìm kiếm một phần tử trong một cây.
- Duyệt tiền thứ tự: duyệt một cây theo cách thức duyệt tiền thứ tự (tham khảo chương sau).
- Duyệt trung thứ tự: duyệt một cây theo cách thức duyệt trung thứ tự (tham khảo chương sau).
- Duyệt hậu thứ tự: duyệt một cây theo cách thức duyệt hậu thứ tự (tham khảo chương sau).
Thuật toán trong C++
Khái niệm
Thuật toán trong lập trình máy tính là tập hợp các hướng dẫn rõ ràng, có thể thực hiện để giải quyết một vấn đề cụ thể Nó yêu cầu đầu vào xác định để xử lý và tạo ra kết quả mong muốn, giúp tối ưu hóa quá trình xử lý dữ liệu Thuật toán đóng vai trò quan trọng trong việc xây dựng các ứng dụng và phần mềm, đảm bảo hoạt động hiệu quả và chính xác.
Một thuật toán để thêm hai số:
- Lấy hai đầu vào số
- Thêm số bằng toán tử +
6.2 Các phẩm chất của thuật toán:
- Đầu vào và đầu ra phải được xác định chính xác.
- Mỗi bước trong thuật toán phải rõ ràng và rõ ràng.
- Thuật toán nên hiệu quả nhất trong số nhiều cách khác nhau để giải quyết một vấn đề.
Một thuật toán không cần phải bao gồm mã máy tính cụ thể mà thay vào đó nên được viết dưới dạng ngôn ngữ chung để dễ dàng chuyển đổi sang các ngôn ngữ lập trình khác nhau Điều này giúp đảm bảo tính linh hoạt và khả năng vận dụng của thuật toán trong nhiều môi trường lập trình khác nhau Viết thuật toán theo cách này sẽ tối ưu hóa khả năng tái sử dụng và chia sẻ kiến thức trong cộng đồng lập trình viên.
6.3 Ví dụ về thuật toán trong C++
VD1: Cộng hai số do người dùng nhập:
Bước 2: Khai báo các biến num1, num2 và sum
Bước 3: Đọc giá trị num1 và num2
Bước 4: Thêm num1 và num2 và gán kết quả thành tổng sum ← num1 + num2
VD2: Tìm số lớn nhất trong 3 số:
Bước 2: Khai báo các biến a, b và c
Bước 3: Đọc các biến a, b và c
Hiển thị a là số lớn nhất
Hiển thị c là số lớn nhất
Hiển thị b là số lớn nhất
Hiển thị khác c là số lớn nhất
PHẦN 2: CHƯƠNG TRÌNH ỨNG DỤNG ( NHÓM ):
1 Lý do chọn đề tài: Trong sự phát triển của khoa học cuối thế kỉ XX đầu thế kỉ
Trong bối cảnh XXI, công nghệ thông tin hiện nay là ngành có tốc độ phát triển nhanh nhất, đóng vai trò quan trọng trong các ngành khoa học công nghệ của đất nước Mặc dù công nghệ thông tin ở Việt Nam còn mới, nhưng tốc độ phát triển của nó rất mạnh mẽ, góp phần thúc đẩy các lĩnh vực khác nhau Một trong những lĩnh vực ứng dụng tin học phổ biến nhất tại Việt Nam là lĩnh vực quản lý, giúp nâng cao hiệu quả và độ chính xác trong công tác quản lý nhà nước và doanh nghiệp.
Việc ứng dụng công nghệ thông tin trong quản lý sinh viên đã mang lại hiệu quả rõ rệt, giúp các nhà quản lý điều hành công việc một cách khoa học, chính xác và hiệu quả hơn Tin học hóa trong quản lý đã là một bước tiến quan trọng, nâng cao năng suất và giảm thiểu sai sót trong quá trình quản lý Chính vì vậy, nhóm chúng em đã chọn đề tài hướng đến việc ứng dụng công nghệ thông tin vào công tác quản lý sinh viên, nhằm nâng cao chất lượng và hiệu quả quản lý trong nhà trường.
“Xây dựng chương trình quản lý sinh viên C++” làm nghiên cứu.
Chương trình “Quản lý sinh viên” được xây dựng nhằm hỗ trợ công tác quản lý thông tin sinh viên, điểm số và các dữ liệu liên quan một cách hiệu quả Việc phân tích và thiết kế hệ thống thông tin là yếu tố then chốt để đảm bảo dữ liệu được tổ chức một cách khoa học, dễ dàng truy cập và cập nhật Quản lý sinh viên là cần thiết để nâng cao hiệu quả công việc, giảm thiểu thời gian và công sức cho cán bộ, nhân viên trong việc xử lý dữ liệu Hệ thống quản lý thông tin sinh viên giúp tiết kiệm thời gian, tăng tính chính xác và hỗ trợ công tác quản lý đào tạo, nắm bắt tình hình sinh viên một cách nhanh chóng Việc áp dụng phương pháp quản lý phù hợp sẽ giúp hệ thống hoạt động hiệu quả, đáp ứng yêu cầu quản lý ngày càng cao của nhà trường.
Trong bài toán “Quản lý sinh viên”, mỗi sinh viên có các thuộc tính như mã số sinh viên, tên, lớp, giới tính, ngày sinh, điểm rèn luyện, cùng các môn học gồm Anten, tín hiệu, tin học, lập trình, tiếng Anh Hệ thống sẽ tính trung bình cộng điểm của các môn học này để đánh giá tổng thể kết quả học tập của từng sinh viên.
-Khi xuất ra màn hình sẽ có đầy đủ thông tin cần thiết theo yêu cầu đã đề ra cho mỗi sinh viên.
+In danh sách sinh viên.
+Xuất ra tổng sinh viên hiện tại.
+Xóa tất cả sinh viên.
+Chỉnh sửa sinh viên( chỉnh sửa các thuộc tính hiện có).
+Tìm kiếm 1 sinh viên theo mã số.
+Xóa 1 sinh viên theo mã số.
+Sắp xếp sinh viên theo điểm rèn luyện ( tăng hoặc giảm).
3 Nội dung lý thuyết:(Tính chất hướng đối tượng, cấu trúc dữ liệu trong bài toán, đồ họa - đưa một số đoạn code ví dụ)
(1) Tính chất hướng đối tượng trong bài toán này là tính chất kế thừa.
Kỹ thuật kế thừa là phương pháp cho phép tái sử dụng các tính năng có sẵn của đối tượng khác, giúp giảm thiểu việc viết mã lặp lại Điều này tối ưu hóa quá trình phát triển phần mềm bằng cách xử lý các công việc tương tự một cách hiệu quả Kế thừa không những tiết kiệm thời gian lập trình mà còn nâng cao tính mở rộng và bảo trì của hệ thống Đây là một trong những nguyên tắc cốt lõi trong lập trình hướng đối tượng, giúp tạo ra những ứng dụng linh hoạt và dễ quản lý.
-Một số ví dụ trong bài toán có tính kế thừa:
+Trước hết ta có 3 hàm bỗ trợ cho các hàm nhập điểm, ngày, tháng, năm,…: double stringToDouble(string s) { stringstream geek(s); int diem; geek >> diem; return diem;
To convert a string to an integer in C++, you can use the stringstream object to extract the numeric value, ensuring accurate type conversion When validating user input to check if a string represents a valid number, you should iterate through each character to verify that all characters are digits, confirming the input's numerical validity Proper input validation and type conversion techniques are essential for robust C++ programming, especially when handling user-provided data to prevent errors and ensure reliable application behavior.
+Sau đây là hàm kiểm tra nhập điểm được kế thừa các tính năng của 2 hàm trên: bool kiemTraNhapDiem(string s) { bool check = kiemTraNhapSo(s); if (!check) { return false;
}int diem = stringToInt(s); if (diem >= 0 && diem 10.
-Về hàm nhập tháng: bool kiemTraNhapThang(string s) { bool check = kiemTraNhapSo(s); if (!check) { return false;
}int thang = stringToInt(s); if (thang >= 0 && thang 12.
-Tương tự cho các hàm nhập ngày và nhập năm.
+Đối với nhập ngày thì:
• Khi nhập vào các tháng 1,3,5,8,10,12: chỉ cho phép nhập số và nằm trong khoảng từ 1 -> 31.
•Khi nhập vào các tháng 4,6,7,9,11: chỉ cho phép nhập số và nằm trong khoàng từ 1 -> 30.
•Khi nhập vào tháng 2: chỉ cho phép nhập số và nằm trong khoảng từ 1 -> 28 hoặc 29.
(2) Cấu trúc dữ liệu trong bài toán:
-Cấu trúc dữ liệu được sử dụng trong bài toán quản lý này là danh sách liên kết đơn.- Được thể hiện ở những dòng code sau:
-Đây là khai báo 1 Node trong danh sách liên kết đơn.
Trong cấu trúc dữ liệu, thuộc tính `int data` đại diện cho dữ liệu của mỗi node, có thể là kiểu số nguyên hoặc các kiểu dữ liệu khác như float hoặc cấu trúc SinhVien, tùy thuộc vào mục đích sử dụng Việc lựa chọn kiểu dữ liệu phù hợp giúp tối ưu hóa hiệu quả và linh hoạt trong quá trình xử lý dữ liệu của cây hoặc danh sách liên kết Thay đổi kiểu dữ liệu của `data` cho phép ứng dụng mở rộng phạm vi trong các bài toán khác nhau, đáp ứng các yêu cầu đa dạng của chương trình.
Node *next: Là con trỏ mang chính kiểu dữ liệu Node và có chức năng trỏ đến địa chỉ của Node tiếp theo trong danh sách
Từ khóa typedef struct để dễ dàng trong việc gọi và sử dụng NODE sau này!
-Đây là khai báo cấu trúc 1 danh sách liên kết đơn.
NODE* pHead; là node đầu tiên của danh sách
NODE* pTail; là node cuối cùng của danh sách
-Đây là hàm khởi tạo danh sách liên kết đơn.
Ban đầu, khi danh sách liên kết được khởi tạo, các thành phần NODE* pHead và NODE* pTail đều được thiết lập là rỗng (NULL), phản ánh rằng danh sách chưa chứa phần tử nào Hàm khởi tạo đảm nhận việc gán giá trị con trỏ quản lý địa chỉ của pHead và pTail về NULL, giúp đảm bảo danh sách liên kết bắt đầu ở trạng thái trống và sẵn sàng cho các thao tác chèn phần tử sau này Việc này đóng vai trò thiết yếu trong quản lý bộ nhớ và duy trì tính nhất quán của danh sách liên kết ban đầu.
-Đây là hàm kiểm tra danh sách có rỗng hay không.
-Hàm int KiemTraRong(LINKED LIST ds ) dưới đây nhận đầu vào là
Trong danh sách liên kết đơn, việc kiểm tra phần tử đầu và phần tử cuối có là NULL giúp xác định trạng thái của danh sách, đặc biệt là danh sách rỗng Nếu phần tử đầu của danh sách là NULL, điều này đồng nghĩa với việc toàn bộ danh sách liên kết đơn đó cũng rỗng Do đặc thù truy cập tuần tự của danh sách liên kết đơn, chỉ cần kiểm tra phần tử đầu tiên để xác định danh sách có rỗng hay không, giúp tối ưu hóa quá trình kiểm tra và thao tác xử lý danh sách liên kết.
-Đây là hàm tạo 1 Node trong danh sách liên kết đơn.
Trong danh sách liên kết đơn, mỗi NODE được coi như một phần tử của mảng, tuy nhiên NODE khác biệt ở chỗ có hai thành phần chính là dữ liệu (data) và thành phần liên kết (kết nối đến NODE tiếp theo) Để tạo một NODE hoàn chỉnh, chúng ta cần khai báo đầy đủ hai thành phần này, giúp cấu trúc danh sách liên kết hoạt động chính xác và hiệu quả.
Hàm `NODE* taoNode(SV x)` có chức năng tạo ra một NODE mới trong danh sách liên kết đơn Đầu vào của hàm là giá trị `x` kiểu int, và hàm sẽ gán `p->data = x` để lưu trữ dữ liệu vào NODE mới Sau đó, thuộc tính `p->next` của NODE được thiết lập bằng NULL, đảm bảo NODE này không liên kết với phần tử nào khác Hàm này giúp tạo ra một phần tử mới trong danh sách liên kết một cách dễ dàng và hiệu quả.
-Giao diện menu Chương trình:
-Giao diện khi nhập sinh viên (ví dụ: nhập 3 sinh viên):
-Khi nhập xong và nhấn phím bất kì thì giao diện sẽ quay lại như lúc đầu:
+Khi nhập 1 mã số đã có trong danh sách sẽ báo lỗi sau:
+Khi nhập giới tính thì chỉ cho phép nhập ‘nam’ hoặc ‘nu’, nếu nhập các kí tự khác thì sẽ báo lỗi:
+Khi nhập tháng sinh của sinh viên thì chỉ cho nhập số và nằm trong khoảng từ 1 đến 12:
-Đến khi nhập ngày sinh thì sẽ dựa vào tháng sinh :
+Các tháng 1,3,5,8,10,12: thì chỉ đc nhập trong khoảng từ ngày 1 -> 31.
+Tương tự cho các tháng 4,6,7,9,11: thì chỉ đc nhập trong khoảng từ ngày 1 -> 30. +Tháng 2: chỉ đc nhập trong khoảng từ ngày 1 -> 28 hoặc 29.
-Nhập năm sinh của sinh viên:
+Chỉ được nhập số và nhập trong khoảng từ 1 -> 2022.
-Khi nhập điểm rèn luyện ( nhập từ 0- > 100) và điểm của các môn học theo hệ số
-Giao diện khi in danh sách sinh viên( ví dụ 3 sinh viên):
-Giao diện khi in tổng sinh viên hiện tại:
-Giao diện khi chinh sửa sinh viên:
+Giao diện khi chỉnh sửa điểm của 1 sinh viên:
-Giao diện sắp xếp sinh viên theo điểm rèn luyện:
1.Hướng dẫn thực hiện Chương trình:
-Bước 1: chọn mục 1 trên menu để nhập sinh viên ( lưu ý chỉ được nhập 1 lần 1 sinh viên).
-Bước 2: chọn các mục sau để cài đặt:
4.Xóa tất cả sinh viên.
6.Tìm kiếm sính viên(theo mã số).
7.Xóa 1 sinh viên (theo mã số).
8.Sắp xếp sinh viên (theo điểm rèn luyện).
-Bước 3:Nhấn phím 0 để thoát khỏi giao diện thực hiện chương trình.