Hàm sử dụng hàm GetNode để tạo một nút mới trong danh sách liên kết và gán giá trị value cho nút... Thuật toán duyệt danh sách liên kết Bước 1: Khởi tạo một con trỏ p và gán cho nó bằng
Trang 1
TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN- ĐHQG TPHCM
BỘ GIÁO DỤC VÀ ĐÀO TẠO
«e1
Giảng viên hướng dẫn : Trần Huy Quang
Sinh viên thực hiện:
Trang 2MUC LUC
4109) ittei09) cu) 0n" 3
II CÁC CẤU TRÚC DỮ LIỆU SỬ DỤNG 22 2222222 22221 3
II THUẬT TOÁN CỦA CHƯƠNG TRÌNH TỔỐNG THỂ - 2222222222 12113E211xr.Errkrrrr 3
IV THUẬT TOÁN CỦA CÁC LỆNH XỬ LÝ DỮ LIỆU . 222- 222222 222ecrrErrerrrrrrrrrrrrreee 3
1 Thuật toán đọc dữ liệu input.txt và đưa vào danh sách liên kết 3
2, Thuật toán duyệt danh sách liên kết St rree 5
3 Thêm vào đầu danh sách liên kết -255- 2222 s22 x2 rrgtrrrrerrrrerrrrrrrrrree 5
4 Thêm vào cuối danh sách liên kết - 2-5 22c 22t EE2rEExrrtrrrrrrrrrrrerrrrrir 6
5 Thêm vào danh sách liên kết ở 1 vị trí bất kì - 55c 5S Seecrrerrerkrerkrrrrerkerree 7
6 Thêm vào danh sách liên kết 1 NODE sau các phần tử là số nguyên tố 9 7 Sắp xếp các số nguyên theo thứ tự tăng dần/ giảm dần occcceeecee 10
§ Xóa phần tử ở đầu danh sách liên kết - 222222 222 Y rttEEkttrrrrrttrrrrrrrrrrrrrree 11
10 Xóa phần tử ở cuối danh sách liên kết 222222vv+ttEEEErvrrrrrrtrrrrrrrrrrer 12
11 Xóa phần tử ở một vị trí bất kì trong danh sách liên kết .- - 13
12 Xóa toàn bộ phần tử là số nguyên tố -:5ccccnnnttttririrrirrrriiiiiirrre 14
13 Sửa toàn bộ phần tử là số chẵn thành 1 giá trị do người dùng nhập từ bàn phím 15
14 Hủy toàn bộ danh sách liên kết - tre 15
V THUẬT TOÁN CỦA CÁC CHỨC NĂNG CHƯƠNG TRÌNH 2- 22ccccrrerrrrrrree 16
1 Chức năng 1 và 2: Undo (phục hồi lệnh gần nhất) và Redo (lặp lại lệnh gần nhất) 16
2 Chức năng 3: Save (lưu dãy số vào tập tin output.txt vào trên 1 đòng) 20
3 Chức năng 4: Reset (Khởi tạo lại phiên làm việc) - eee tee eee eee eee neni 21
4 Chức năng 5: Quit (Kết thúc chương trình) - ni 21
Trang 3I Y TUONG CHUONG TRINH
Chương trình sử dụng danh sách liên kết đơn để lưu trữ dãy số nguyên dương được
đọc từ tập tin input.txt Người dùng có thể thực hiện các lệnh xử lý dữ liệu để thay
đổi nội dung danh sách và các chức năng khác để quản lý phiên làm việc Các lệnh
xử lý dữ liệu bao gồm thêm, xóa và sửa phần tử trong danh sách Các chức năng
khác bao gồm undo, redo, save, reset và quit
Toàn bộ các source minh hea cho các hàm trong bai lam sẽ được miêu tả khái quát
dưới dạng mã giả (pseudo code)
II CÁC CẤU TRÚC DỮ LIỆU SỬ DỤNG
Chương trình sử dụng cấu trúc danh sách liên kết đơn để lưu trữ các phần tử với: Cấu trúc NODE gồm hai trường đữ liệu là data và pNext Trường data lưu trữ giá trị của một phần tử trong danh sách và trường pNext là con trỏ trỏ tới phần tử tiếp theo trong danh sách
Cấu trúc LIST gồm hai trường đữ liệu là pHead và pTail Trường pHead là con trỏ trỏ tới phần tử đầu tiên trong danh sách và trường pTail là con trồ trô tới phần tử cuối cùng trong danh sách
II THUẬT TOÁN CỦA CHƯƠNG TRÌNH TỔNG THE
Khởi tạo danh sách liên kết ban đầu từ dữ liệu trong tập tin input.txt Hiển thị menu chức năng và yêu cầu người dùng chọn chức năng cần thực
Nếu chức năng đó là kết thúc chương trình, thoát chương trình
Chỉ tiết hơn về từng chức năng được thực hiện trong các hàm riêng biệt
IV THUẬT TOÁN CỦA CÁC LỆNH XỬ LÝ DỮ LIỆU
1 Thuật toán đọc di liéu input.txt va đưa vào danh sách liên kết
Trang 4Bước 1: Khai báo cấu trúc NODE gồm int data, NODE *pNext
Bước 2: Khai báo cấu trúc LIST chứa con trô pHead và pTail (Ta sẽ sử dụng cấu trúc
dữ liệu đã được khai báo ở 2 bước này cho toàn bài)
Bước 3: Viết hàm GetNode với tham số truyền vào là 1 số nguyên Hàm GetNode có công dụng là cấp phát bộ nhớ động để tạo ra một đối tượng NODE mới và trả về con trỏ tới đối tượng đó Điều này cho phép ta tạo ra các đối tượng NODE trong quá trình chương trình chạy và quản lý chúng thông qua các con trỏ
Sau đây là mã giả miêu tả hàm GetNode:
function GetNode (DATA) :
NODE *p = new NODE
Bước 4: Khai báo và gọi hàm đọc dữ liệu từ tập tin và tạo danh sách liên kết
Source minh hoa bang mA gia:
function readDataFromFile(Ll: LIST) :
infile < -open file "input.txt"
value < -read next value from infile
hàm đọc giá trị đầu tiên từ tệp tin và gán cho biến value Hàm sử dụng hàm
GetNode để tạo một nút mới trong danh sách liên kết và gán giá trị value cho nút
Trang 5đó Nút này được gán cho con trỏ l.pHead và I.pTail để đánh dấu nút đầu tiên và nút cuối của danh sách Tiếp theo, hàm sử dụng một con trỏ current để theo dõi nút hiện tại trong danh sách Con trỏ này được khởi tạo ban đầu trỏ tới nút đầu tiên (LpHead) Trong vòng lặp, hàm đọc các giá trị tiếp theo từ tệp tin và tạo nút mới cho mỗi giá trị đó bằng cách sử dụng hàm GetNode Nút mới này được gán cho
current->pNext để thiết lập liên kết với nút hiện tại Sau đó, con trỏ current được cập nhật để trỏ tới nút mới, và l.pTail cũng được cập nhật để trỏ tới nút cuối của
danh sách Sau khi đọc xong dữ liệu từ tệp tin, hàm đóng tệp tin để giải phóng tài
nguyên Tổng quát, đoạn code trên cho phép đọc dữ liệu từ tệp tin và tạo danh sách
liên kết tương ứng Nút đầu tiên và nút cuối của danh sách được theo dõi bằng các con tré LpHead va L.pTail => Kết quả sau khi thực hiện đoạn code này là danh sách
liên kết được tạo và lưu trữ các giá trị đọc được từ tập tin input.txt
2 Thuật toán duyệt danh sách liên kết
Bước 1: Khởi tạo một con trỏ p và gán cho nó bằng địa chỉ của phần tử đầu tiên của danh sách liên kết được truyền vào (tức là l.pHead)
Bước 2: Duyệt qua danh sách liên kết bằng cách kiểm tra điều kiện p != NULL (nghĩa
là chưa duyệt đến phần tử cuối cùng của danh sách)
Bước 3: In ra giá trị của phần tử mà con trỏ p đang trỏ tới bằng cách sử dụng câu lệnh printf('%d”, p->data); với ngôn ngữ C và C++ là cout << p->data;
Bước 4: Di chuyển con trỏ p đến phần tử tiếp theo trong danh sách bằng cách gán
cho p giá trị của con trỏ pNext của phần tử hiện tại
Bước 5: Lặp lại các bước 2-4 cho đến khi con trỏ p trỏ tới phần tử cuối cùng trong danh sách (tức là p = NULL)
=> Kết quả của thuật toán là các phần tử trong danh sách liên kết được in ra màn
hình
Source minh hoa:
function OutPut(1l: LIST) :
for p = 1 pHead to p!= NULL do :
Trang 6Ta goi ham void AddFirst (LIST &l, NODE *p)- với 2 thông số truyền vào là LIST
&l (chứa con trỏ pHead va pTail) va mét NODE *p
1 Kiém tra néu danh sach lién két | réng (ttc la |.pHead = NULL), tức là không
có phần tử nào trong danh sách, thì gán nút p vào cả đầu lẫn cuối của danh sách bằng lệnh I.pHead = I.pTail = p
2 Nếu danh sách liên kết l không rỗng, tức là đã có phần tử trong danh sách, thì tiến hành thêm nút p vào đầu danh sách bằng cách:
„ _ Gán con trỏ pNext của nút p bằng con trỏ pHead của danh sách liên kết | (tite
function AddFirst(l: LIST, p : NODE) :
if 1.pHead == NULL then
4 Thêm vào cuối danh sách liên kết
Ta goi ham void AddTail (LIST &1, NODE *p)- với 2 thông số truyền vào là LIST &l (chứa con trỏ pHead và pTail) và một NODE *p
Thuật toán được thực hiện như sau:
1 Kiểm tra nếu danh sách liên kết l rỗng (tức là l.pHead = NULI), tức là không
có phần tử nào trong danh sách, thì gán nút p vào cả đầu và cuối danh sách bằng lệnh I.pHead = I.pTail = p
2 Nếu danh sách liên kết l không rỗng, tức là đã có phần tử trong danh sách, thì tiến hành thêm nút p vào cuối danh sách bằng cách:
Trang 7„ - Gán con trỏ pNext của phần tử cuối cùng của danh sách liên kết l (tức là l.pTail->pNext) bằng con tré p của nút mới được thêm vào (tức là l.pTail-
>pNext = p)
« - Cập nhật lại con trỏ pTail của danh sách liên kết I để trổ tới nút mới được
thêm vào (tức là l.pTail = p)
=> Kết quả của thuật toán là danh sách liên kết I sau khi đã thêm nút p vào cuối danh sách
Source minh hoa:
function AddTail(l: LIST, p : NODE) :
if 1.pHead == NULL then
5 Thém vao danh sach lién két 61 vi tri bat ki
*Thuật toán cho Hàm InsertBefore (Thêm vào trước)
e _ BI; Nhận đầu vào là một tham chiếu đến một con trỏ nút đang tồn tại và một
giá trị số nguyên k
se _ B2: Khởi tạo một con trỏ nút p và cấp phát động bộ nhớ cho nó bằng cách sử dung ham malloc()
e B3: Kiém tra xem con tré p có bang NULL không Nếu có, in ra thông báo lỗi
và thoát khỏi chương trình bằng lệnh exit(0)
e B4: Sao chép nội dung của nút đã cho vào con trỏ p bằng cách sử dụng toán
tử * dé gan con trỏ p bằng giá trị của con trỏ đã cho (*p = *Q)
e B5: Dat con tré next của con trỏ q trỏ đến con trỏ p
e B6: Đặt giá trị của khóa trong nút đã cho bằng giá trị k
Kết quả là nút mới chứa giá trị k được chèn vào danh sách liên kết đơn trước nút
đã cho, và danh sách liên kết đơn được cập nhật để trỏ đến nút mới này Source minh hoa:
function insertBefore(q: NODE, k : int) :
Trang 8Các bước được thực hiện bởi hàm insertAt() nhu sau:
B1: Nhận đầu vào là một cấu trúc dữ liệu LIST I g6m con trỏ đầu danh sách head, con trỏ cuối danh sách tail, vị tri pos và giá trị số nguyên k cần chèn
B2: Xác định số lượng nút hiện có trong danh sách liên kết bằng cách tính độ
dài danh sách sử dụng hàm length()
B3: Kiểm tra xem vị trí chèn có hợp lệ hay không Nếu vị trí pos nhỏ hơn 0
hoặc lớn hơn n thì in thông báo lỗi và trả về
B4: Nếu vị trí pos la 0, goi ham addFirst() dé chèn nút mới vào đầu danh sách B5: Nếu vị trí pos là n, gọi hàm addLast() dé chén nut mới vào cuối danh sách B6: Nếu vị trí pos nằm giữa đầu và cuối danh sách, thực hiện vòng lặp for để tìm nút tại vị trí pos - 1 và trỏ q đến nút đó
B7: Gọi hàm insertBeforeQ để chèn nút mới vào trước nút tại vị trí pos
B8: Nếu nút được chèn vào cuối danh sách, cập nhật con trỏ tail trỏ đến nút mới được chèn
Source minh hoa:
if pos < 0 or pos > n+1 then
print "Ban nhap sai vi tri"
return NULL
else
if pos == 1 then
// Để nhập vào vị trí đuôi (AddTail) ta cần phải thêm vào vị trí n+1
else if pos == nt+1 then
AddTail(l, p)
else
i=0
Trang 9
i=i+il q->pNext end while
insertBefore(q, k)
if q == L.pTail then L.pTail < -1l.pTail->pNext endif
endif endif
6 Thêm vào danh sach lién két 1 NODE sau các phần tử là số nguyên tố
*Thuật toán kiểm tra phần tử số nguyên có phải là số nguyên tố hay không
bằng cách gọi hàm bool IsPrime (int k)
se Nếu số nguyên đó là số âm hoặc bằng 1, trả về "không phải số nguyên tố"
se - Duyệt qua các số lẻ từ 2 đến căn bậc hai của số nguyên đó Nếu số nguyên đó chia hết cho một số nằm trong đoạn đó, trả về "không phải số nguyên tố"
se Nếu số nguyên đó không chia hết cho bất kỳ số nào trong đoạn từ 3 đến căn bậc hai của nó, trả về "là số nguyên tố"
Source minh hoa:
Các bước duoc thuc hién béi ham insertBeforePrime() nhu sau:
e Bt: Nhan dau vao la mét cau tric dir liéu LIST | g6m con trỏ đầu danh sách head, con trỏ cuối danh sách tail và giá trị số nguyên cần chèn thêm
« - B2: Khối tạo con trỏ q trô đến đầu danh sách I
Trang 10e B3: Duyét qua cac phần tử trong danh sách liên kết bắt đầu từ phần tử thứ hai Với mỗi phần tử p, ta kiểm tra xem nó có phải là số nguyên tố không bằng cách sử dụng hàm isPrime Nếu là số nguyên tố, ta tạo một nút mới chứa
phần tử cần thêm (phantucanthem) và chèn vào trước p bằng cách cập nhật con trỏ next của q và phần tử p
s _ B4: Cập nhật con trỏ q trỏ đến phần tử p để chuẩn bị cho lần duyệt tiếp theo
e B5: Xét riêng phần tử đầu tiên của danh sách I Nếu nó là số nguyên tố, ta tạo một nút mới chứa phần tử cần thêm (phantucanthem) và chèn vào đầu danh sách l bằng cách sử dụng hàm AddHead
Source minh hoa:
function ThemSauTatCaSoNguyenTo(l: LIST, phantuthemvao : int) :
for p = L.pHead to p != NULL do :
if isPrimeCp->data) then
x = GetNode(phantuthemvao) // Tao nut mdi x
g = p->pNext // Luu trit con tré pNext hién tại
x->pNext = g // Liên kết nút mới x với nút sau nó
p->pNext = x // Liên kết nút p với nút mới x
p = p->pNext // Bỏ qua phần tử vừa thêm để tiếp tục duyệt
endif
endfor
7 Sắp xếp các số nguyên theo thứ tự tăng dần/ giảm dan
« - Hàm HoanVi được sử dụng để hoán đổi giá trị của 2 phần tử x và y
Source minh hoa:
> Ham ‘HoanVi nha n hai bien nguyen ‘x’ va ‘y’ lam tham so Ham nay hoan do i gia tri
cu a hai bie nna y
> Taomo tbientam thoi ‘temp’ va gan gia tri cua ‘x’ vao ‘temp’ de lvutru gia tri ban daucua‘x’
> Gangia tri cua‘y’ vao‘x’,tucla gangia tri cua‘y’ cho ‘x’
Trang 11> Gan gia tri ban đau cu a“x (đươ c lưu trư trong ‘temp’) va o “y, tư cla gan gia tri ban
đa u cu a “X cho “y'
Hàm SapXep nhận đối số đầu vào là danh sách liên kết đơn (J) và phân loại (phanloai) cho biết danh sách sắp xếp tăng dần (t) hay giảm dần (g)
Thuật toán sắp xếp tăng dân:
Duyệt từ đầu danh sách đến nút trước nút cuối cùng
Với mỗi nút p, duyệt từ nút p tiếp theo đến nút cuối cùng
Nếu giá trị nút p lớn hơn giá trị nút q, hoán đổi giá trị của nút p và nút q Thuật toán sắp xếp giảm dan:
Duyệt từ đầu danh sách đến nút trước nút cuối cùng
Với mỗi nút p, duyệt từ nút p tiếp theo đến nút cuối cùng
Nếu giá trị nút p nhỏ hơn giá trị nút q, hoán đổi giá trị của nút p và nút q
Source minh hoa:
function SapXep(l: LIST, phanloai : char) :
for p = L.pHead to p != L.pTaiL do :
if p->data < q->data then
HoanVi(p->data, q->data)
endif endif endfor
8 Xóa phần tử ở đầu danh sách liên kết
- Khai báo hàm deleteBegin(LIST &l) truyền vào danh sách LIST l
Kiểm tra nếu danh sách rỗng (.pHead == NULL) thì không làm gì cả, kết thúc