Lập trình C: Bài 13 – Danh sách liên kết đơn cài bằng con trỏ
Nội dung
- 1. Cài đặt danh sách
- 2 Khởi tạo danh sách rỗng
- 3 Kiểm tra danh sách rỗng hay không
- 4 Tính độ dài danh sách
- 5 Tạo 1 Node trong danh sách
- 6 Chèn Node P vào vị trí đầu tiên
- 7. Chèn Node P vào vị trí k trong danh sách
- 8 Tìm phần tử co giá trị x trong danh sách
- 9 Xóa phần tử ở vị trí đầu tiên
- 10. Xóa phần tư ở vị trí k
- 11. Xóa phần tử có giá trị x
- 12. Chương trình hoàn chỉnh (full)
Danh sách liên kết có thể được cài đặt bằng mảng hoặc bằng con trỏ. Trong bài viết này mình sẽ hướng dẫn các bạn sử dụng con trỏ :), Loại danh sách này gọi tắt là danh sách liên kết đơn
Trong các bài trước mình viết code tất cả đều là chuẩn C, nhưng từ bây giờ mình sẽ xen lẫn chút cấu trúc của C++ nên code trong bài này bạn để trong file *.cpp nhé.
Danh sách liên kết có thể được mô tả như sau:
Trong đó Data là dữ liệu của mỗi Node, có thể là Sinh viên, công nhân,… (có kiểu item, và mình làm đơn giản với số nguyên), Next là con trỏ trỏ tới phần tử tiếp theo.
[qads]
1. Cài đặt danh sách
typedef int item; //kieu cac phan tu dinh nghia la item typedef struct Node //Xay dung mot Node trong danh sach { item Data; //Du lieu co kieu item Node *next; //Truong next la con tro, tro den 1 Node tiep theo }; typedef Node *List; //List la mot danh sach cac Node
2 Khởi tạo danh sách rỗng
void Init (List &L) // &L lay dia chi cua danh sach ngay khi truyen vao ham { L=NULL; //Cho L tro den NULL }
Trong các bài trước để có thể thay đổi được giá trị của đối mà ta truyền vào hàm ta thưòng dùng biến con trỏ (*) và trong lời gọi hàm ta cần có & trước biến tuy nhiên khi chúng ta sử dụng cách truyền địa chỉ ngay khi khởi tạo hàm thì trong lời gọi hàm ta tiên hành truyền biến bình thưòng mà không phải lấy địa chỉ (thêm &) trước biến nữa.
(Đây là một cách truyền địa chỉ cho biến trong hàm ở C++.)
3 Kiểm tra danh sách rỗng hay không
Cái này khỏi giải thích nhiều:
int Isempty (List L) { return (L==NULL); }
4 Tính độ dài danh sách
Ta dùng 1 Node để duyệt từ đầu đến cuối, vừa duyệt vừa đếm
int len (List L) { Node *P=L; //tao 1 Node P de duyet danh sach L int i=0; //bien dem while (P!=NULL) //trong khi P chua tro den NULL (cuoi danh sach thi lam) { i++; //tang bien dem P=P->next; //cho P tro den Node tiep theo } return i; //tra lai so Node cua l }
5 Tạo 1 Node trong danh sách
Việc tạo 1 Node chứa thông tin trong danh sách sẽ giúp ta dễ dàng chèn, xóa và quản lý danh sách hơn. Trước tiên ta sẽ phải cấp phát vùng nhớ cho Node và sau đó gán Data vào là ok
Node *Make_Node (Node *P, item x) //tao 1 Node P chua thong tin la x { P = (Node *) malloc (sizeof (Node)); //Cap phat vung nho cho P P->next = NULL; //Cho truong Next tro den NULL P->Data = x; //Ghi du lieu vao Data return P; }
6 Chèn Node P vào vị trí đầu tiên
Để chèn P vào đầu danh sách trước tiên ta cho P trỏ đến L, sau đó chỉ việc cho L trỏ lại về P là ok
void Insert_first (List &L, item x) //Chen x vao vi tri dau tien trong danh sach { Node *P; P = Make_Node(P,x); //tao 1 Node P P->next = L; //Cho P tro den L L = P; //L tro ve P }
7. Chèn Node P vào vị trí k trong danh sách
Trước tiên ta kiểm tra vị trí chèn có hợp lệ không, nếu hợp lệ kiểm tra tiếp chèn vào vị trí 1 hay k >1 . Với k >1 ta thực hiện duyệt bằng Node Q đến vị trí k-1 sau đó cho P->Next trỏ đến Node Q->Next, tiếp đến cho Q->Next trỏ đến P
void Insert_k (List &L, item x, int k) //chen x vao vi tri k trong danh sach { Node *P, *Q = L; int i=1; if (k<1 || k> len(L)+1) printf("Vi tri chen khong hop le !"); //kiem tra dieu kien else { P = Make_Node(P,x); //tao 1 Node P if (k == 1) Insert_first(L,x); //chen vao vi tri dau tien else //chen vao k != 1 { while (Q != NULL && i != k-1) //duyet den vi tri k-1 { i++; Q = Q->next; } P->next = Q->next; Q->next = P; } } }
8 Tìm phần tử co giá trị x trong danh sách
Ta duyệt danh sách cho đến khi tìm thấy hoặc kết thúc và trả về vị trí nếu tìm thấy, ngược lại trả về 0
int Search (List L, item x) //tim x trong danh sach { Node *P=L; int i=1; while (P != NULL && P->Data != x) //duyet danh sach den khi tim thay hoac ket thuc danh sach { P = P->next; i++; } if (P != NULL) return i; //tra ve vi tri tim thay else return 0; //khong tim thay }
9 Xóa phần tử ở vị trí đầu tiên
Trước tiên ta lưu giá trị của phần tử đầu tiên vào biến x, sau đó tiền hành cho L trỏ đến L->Next
void Del_frist (List &L, item &x) //Xoa phan tu dau tien { x = L->Data; //lay gia tri ra neu can dung L = L->next; //Cho L tro den Node thu 2 trong danh sach }
10. Xóa phần tư ở vị trí k
Dùng P duyệt đến vị trí k-1 và tiến hành cho P->Next trỏ đến phần tư kế tiếp k mà bỏ qua k. Lưu ý trong hình mình quên không lưu lại giá trị cần xóa tuy nhiên các bạn cần lưu lại như khi xóa ở vị trí đầu tiên.
void Del_k (List &L, item &x, int k) //Xoa Node k trong danh sach { Node *P=L; int i=1; if (k<1 || k>len(L)) printf("Vi tri xoa khong hop le !"); //kiem tra dieu kien else { if (k==1) Del_frist(L,x); //xoa vi tri dau tien else //xoa vi tri k != 1 { while (P != NULL && i != k-1) //duyet den vi tri k-1 { P=P->next; i++; } P->next = P->next->next; //cho P tro sang Node ke tiep vi tri k } } }
11. Xóa phần tử có giá trị x
Đon giản là ta tìm x trong danh sách bằng hàm Search và xóa tại vị trí tìm thấy mà ta nhận được
void Del_x (List &L, item x) //xoa phan tu x trong danh sach { while (Search(L,x)) Del_k (L,x,Search(L,x)); //trong khi van tim thay x thi van xoa }
12. Chương trình hoàn chỉnh (full)
#include<stdio.h> #include<stdlib.h> typedef int item; //kieu cac phan tu dinh nghia la item typedef struct Node //Xay dung mot Node trong danh sach { item Data; //Du lieu co kieu item Node *next; //Truong next la con tro, tro den 1 Node tiep theo }; typedef Node *List; //List la mot danh sach cac Node void Init (List &L); //khoi tao danh sach rong int len (List L); // Do dai danh sach Node *Make_Node (Node *P, item x); //Tao 1 Node P voi thong tin chu trong no void Insert_first (List &L, item x); //Chen phan tu vao dau danh sach void Insert_k (List &L, item x, int k); //Chen phan tu vao vi tri k trong danh sach void Input (List &L);//Nhap danh sach void Output (List L);//Xuat danh sach int Search (List L, item x); //Tim phan tu x trong danh sach, ham tre ve vi tri cua phan tu tim duoc void Del_frist (List &L, item &x); //Xoa phan tu dau danh sach void Del_k (List &L, item &x, int k); //Xoa phan tu vi tri k trong danh sach void Del_x (List &L, item x);//Xoa phan tu co gia tri x trong danh sach void Init (List &L) // &L lay dia chi cua danh sach ngay khi truyen vao ham { L=NULL; //Cho L tro den NULL } int Isempty (List L) { return (L==NULL); } int len (List L) { Node *P=L; //tao 1 Node P de duyet danh sach L int i=0; //bien dem while (P!=NULL) //trong khi P chua tro den NULL (cuoi danh sach thi lam) { i++; //tang bien dem P=P->next; //cho P tro den Node tiep theo } return i; //tra lai so Node cua l } Node *Make_Node (Node *P, item x) //tao 1 Node P chua thong tin la x { P = (Node *) malloc (sizeof (Node)); //Cap phat vung nho cho P P->next = NULL; //Cho truong Next tro den NULL P->Data = x; //Ghi du lieu vao Data return P; } void Insert_first (List &L, item x) //Chen x vao vi tri dau tien trong danh sach { Node *P; P = Make_Node(P,x); //tao 1 Node P P->next = L; //Cho P tro den L L = P; //L tro ve P } void Insert_k (List &L, item x, int k) //chen x vao vi tri k trong danh sach { Node *P, *Q = L; int i=1; if (k<1 || k> len(L)+1) printf("Vi tri chen khong hop le !"); //kiem tra dieu kien else { P = Make_Node(P,x); //tao 1 Node P if (k == 1) Insert_first(L,x); //chen vao vi tri dau tien else //chen vao k != 1 { while (Q != NULL && i != k-1) //duyet den vi tri k-1 { i++; Q = Q->next; } P->next = Q->next; Q->next = P; } } } int Search (List L, item x) //tim x trong danh sach { Node *P=L; int i=1; while (P != NULL && P->Data != x) //duyet danh sach den khi tim thay hoac ket thuc danh sach { P = P->next; i++; } if (P != NULL) return i; //tra ve vi tri tim thay else return 0; //khong tim thay } void Del_frist (List &L, item &x) //Xoa phan tu dau tien { x = L->Data; //lay gia tri ra neu can dung L = L->next; //Cho L tro den Node thu 2 trong danh sach } void Del_k (List &L, item &x, int k) //Xoa Node k trong danh sach { Node *P=L; int i=1; if (k<1 || k>len(L)) printf("Vi tri xoa khong hop le !"); //kiem tra dieu kien else { if (k==1) Del_frist(L,x); //xoa vi tri dau tien else //xoa vi tri k != 1 { while (P != NULL && i != k-1) //duyet den vi tri k-1 { P=P->next; i++; } P->next = P->next->next; //cho P tro sang Node ke tiep vi tri k } } } void Del_x (List &L, item x) //xoa phan tu x trong danh sach { while (Search(L,x)) Del_k (L,x,Search(L,x)); //trong khi van tim thay x thi van xoa } void Input (List &L) //nhap danh sach { int i=0; item x; do { i++; printf ("Nhap phan tu thu %d : ",i); scanf("%d",&x); if (x != 0) Insert_k(L,x,len(L)+1); } while(x != 0); //nhap 0 de ket thuc } void Output (List L) //xuat danh sach { Node *P=L; while (P != NULL) { printf("%5d",P->Data); P = P->next; } printf("\n"); } int main() { List L; Init(L); Input(L); Output(L); int lua_chon; printf("Moi ban chon phep toan voi DS LKD:"); printf("\n1: Kiem tra DS rong"); printf("\n2: Do dai DS"); printf("\n3: Chen phan tu x vao vi tri k trong DS"); printf("\n4: Tim mot phan tu trong DS"); printf("\n5: Xoa phan tu tai vi tri k"); printf("\n6: XOa phan tu x trong DS"); printf("\n7: Thoat"); do { printf("\nBan chon: "); scanf("%d",&lua_chon); switch (lua_chon) { case 1: { if (Isempty(L)) printf("DS rong !"); else printf ("DS khong rong !"); break; } case 2: printf ("Do dai DS la: %d.",len(L));break; case 3: { item x; int k; printf ("Nhap phan tu can chen vao DS: "); scanf("%d",&x); printf ("Nhap vi tri can chen: "); scanf ("%d",&k); Insert_k (L,x,k); printf ("DS sau khi chen:\n"); Output(L); break; } case 4: { item x; printf ("Moi ban nhap vao phan tu can tim: "); scanf("%d",&x); int k=Search(L,x); if (k) printf ("Tim thay %d trong DS tai vi tri thu: %d",x,k); else printf ("Khong tim thay %d trong danh sach !",x); break; } case 5: { int k; item x; printf ("Nhap vi tri can xoa: "); scanf ("%d",&k); Del_k (L,x,k); printf ("DS sau khi xoa:\n"); Output(L); break; } case 6: { item x; printf ("Nhap phan tu can xoa: "); scanf ("%d",&x); Del_x (L,x); printf ("DS sau khi xoa:\n"); Output(L); break; } case 7: break; } }while (lua_chon !=7); return 0; }
[rps-include post=”2703″ shortcodes=”false”]
Hi host, bai viet rat chi tiet va ti mi. Thanks host da danh thoi gian de share voi moi nguoi.
Minh co mot thac mac: void Init (List &L) hinh nhu C khong co toan tu & khi truyen tham so vao trong 1 function, cach dung nay chi su dung cho C++. Nho host check lai gium 🙂
Neu minh muon su dung cau truc cua C thi minh truyen vao nhu the nay (List *L) phai khong host?
Đúng rồi bạn. 🙂
Bài này làm sao a Quân
Cho một danh sách liên kết đơn có nút đầu danh sách trỏ bởi p. Giá trị của trường INFO trong các nút giả sử là các số khác nhau và các nút đã được sắp xếp theo thứ tự tăng dần của giá trị này. Hãy viết hàm để thực hiện:
– Bổ sung một nút mới mà trường INFO có giá trị là X, vào danh sách.
– Loại bỏ một nút mà trường INFO có giá trị bằng K cho trước.
Chào bạn, cảm ơn bạn đã khích lệ. Ở đầu bài mình có nói rồi mà: “Trong các bài trước mình viết code tất cả đều là chuẩn C, nhưng từ bây giờ mình sẽ xen lẫn chút cấu trúc của C++ nên code trong bài này bạn để trong file *.cpp nhé”
Bạn ơi cho mình hỏi một tẹo thôi, không liên quan tới bài tập nhưng làm sao để có được cái môi trường soạn thảo code c++ này hả bạn?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
void Insert_k (List &L, item x, int k) //chen x vao vi tri k trong danh sach
{
Node *P, *Q = L;
int i=1;
if (k len(L)+1) printf(“Vi tri chen khong hop le !”); //kiem tra dieu kien
else
{
P = Make_Node(P,x); //tao 1 Node P
if (k == 1) Insert_first(L,x); //chen vao vi tri dau tien
else //chen vao k != 1
{
while (Q != NULL && i != k-1) //duyet den vi tri k-1
{
i++;
Q = Q->next;
}
P->next = Q->next;
Q->next = P;
}
}
}
Những số 1,2,3,4,5,6… ý bạn ạ 🙂 Cảm ơn bạn nhá
Ý bạn hỏi là trình soạn thảo trên máy tính hay là bạn viết trên web?
Nếu trên máy tính thì bạn tìm cách (search google) theo cái bạn dùng để hiện thị số dòng. VD hiển thị số dòng trong dev-C.
Nếu là trên web thì bạn xem các plugin hiển thị code nhé, VD wordpress mình dùng cái SyntaxHighlighter, bạn xem ở đây:
https://www.cachhoc.net/2014/06/18/wordpess-hien-thi-code-tren-wordpress-voi-syntax-highlighted-posting-source-code-on-wordpress-with-syntax-highlighted/
Hic. Mình muốn lưu đuôi .c để viết lại học theo , nhưng nó ko chạy dc . Giờ muốn chuyển bài trên từ .cpp sang .c thi mình phải làm ntn . huhu
Thì bạn chuyển từ kiểu tham chiếu trong C++ sang kiểu con trỏ của C là đuợc.
Em thắc mắc trong các hàm xoá node anh không giải phóng bộ nhớ của (các) node đó. Như vậy sẽ gây lãng phí bộ nhớ đúng không anh? Xin cảm ơn.
Đúng rồi bạn. Cảm ơn bạn đã góp ý. Mình sẽ nhanh chóng sửa lại.
chào anh, theo như bạn Hoàng Duy đã nói phía trên, thì mh k giải phóng thì gây lãng phí, nhưng e có thắc mắc là mh khai báo cái Node đó trong hàm, vậy nó là biến cục bộ, khi thoát hàm nó sẽ biến mất… không biết ý e như v có đúng k nữa. mong anh giải thích thêm. e cảm ơn anh. :))
Ah về cái này cần xem biến đó khai báo theo con trỏ hay ko. Vd Note *P là con trỏ thì ko mất.
Anh cho hỏi cái chỗ tạo 1 node sao lại có *, *Make_Node ý ạ
Thi hàm đó trả về 1 con trỏ cấu trúc – tức là 1 Node mà bạn.
hi a, a giúp e được k ạ
a) Tạo một ngăn xếp bằng danh sách liên kết gồm các số tự nhiên ( số phần
tử do người dùng nhập vào)
b) Đếm xem trong trong ngăn xếp có bao nhiêu phần tử thỏa mãn điều kiện
chia hết cho 3
Em chào anh Nguyễn Văn Quân. Em đang gặp một chút rắc rối khi làm bài tập lớn. Mong anh giải đáp giùm!!! Yêu cầu bài toán là tính toán với các phép toán trên đa thức trên trường số nguyên. em phải viết code cho hàm đọc file input và định nghĩa các phép toán ADD ,SUB, MUD, DIV, MOD.
thứ tự thực hiện phép toán từ trái qua phải ko phân biệt phép toán .bài này sử dụng cấu trúc biểu thức chứa đa thức, đa thức chứa đơn thức và danh sách liên kết.
ví dụ:input.txt:
1 3 6 2 -3 0 ///x^3+6*x^2-3
ADD
6 2 -7 1 4 0 ///6*x^2-7*x+4
DIV
1 2 -1 1 ///x^2-x
thì output là:
1 1 13 0 ////x+13
(thứ tự thực hiện phép toán là phép cộng ADD trước, DIV sau). khi đọc file theo từng dòng nếu cho biến int k= 0 chạy lần lượt từ đầu file được k lẻ là hệ số đơn thức, k chẵn là số mũ đơn thức. vậy làm thế nào để kết nối các đơn thức lại với nhau và cho nó nằm trong đa thức?!?
Em rất mong nhận được lời giải đáp của anh!!!
Em cảm ơn anh nhiều!!!
Cài dạng này liên quan đến cây biẻu thức, nhưng rất tiếc và xin lỗi hiện tại mình chưa tìm hiểu về nó nên không thể giúp gì được cho bạn.
dạ,
cảm ơn anh !
anh ơi,anh có thể thêm các bài viết về cây,các thuật toán tìm kiếm và đồ thị được ko ạ?
Cây thì có một số bài ở đây: https://www.cachhoc.net/category/thuat-toan/cay/
Đồ thị cũng có một số: https://www.cachhoc.net/category/thuat-toan/do-thi/
Còn tìm kiếm thì chưa có sao ý, sẽ cố gắng viết 😉
Anh Quân cho em hỏi là tại sao có lỗi
Error 2 error C4700: uninitialized local variable ‘P’ used
này ạ, em giải phòng rồi nhưng vẫn không chạy được. Em cảm ơn a.
Nó báo là biến P chưa được khởi tạo bạn ah.
giải quyết cái này bằng cách nào vậy bạn?
cho mình hỏi làm sao để nhận biết nên dùng danh sách liên kết hay danh sách đặc trong khi đề bài không nói rõ ah?
Thường thì đề bài sẽ nêu nhưng nếu không thì tùy vào đặc trưng của kiểu dữ liệu và cách thao tác. Ví dụ dữ liệu không cố định và có thể thêm bớt bất cứ lúc nào thì dùng danh sách liên kết và ngược lại.
cho mình hỏi, nếu mình xây dựng một số hàm dslk như trên rồi và nếu mình muốn sử dụng cho một cấu trúc khác mà mình ko muốn viết lại code thì có thể định nghĩa cấu trúc đó theo Node được ko? nếu được thì định nghĩa ntn??? =]]
Được bạn ah, Bạn chỉ cần thay đổi cái kiểu item (mình để là int) thành kiểu khác (float, struct…) là xong (ah, do mình chưa có viết riêng hàm nhập xuất nên bạn cũng cần viết thêm cho kiểu của bạn nhé)
– cho mình hỏi là bài trên phần hàm Insert_k, chỗ xét điều kiện tại sao lại là “k>len(L)+1” vậy ?
VD: có 3 phần tử thì theo hàm len thì len= 3, theo mình nghĩ thì k>3 là dc, tại sao là k>3+1?
– bài viết của a rất bổ ích, cảm ơn a đã chia sẽ.
Vì vị trí là 1,2,3 do đó mình có thể chèn vào vị trí 1,2,3,4 chứ nếu chỉ > k thì lại không có 4 (cuối ds)
Oh, thanks
Bài viết của anh rất chi tiết. Cám ơn anh nhiều
Cảm ơn bạn. hãy chi sẻ cho bạn bè nhé
Anh ơi cái Output của anh nó bị sai rồi. Em test thử trên VS 2015 thì nó không xuất ra đúng kết quả.
Mình code trên dev-C nên có thể nó khác bạn ah.
Vậy muốn nó có thể xuất ra mình nên làm như thế nào bây giờ anh ? Em có thử sửa lại vài chổ nhưng nó vẫn không ra được kết quả.
Cái này mình cũng không rõ vì không dùng vs.
Mấy bài này có bác nào viết đc bằng pascal k viết cho e với e sắp thi r
🙁
Phunghoang070393@gmail.com nha các bác
A cho e hỏi chút.bây giờ em muốn sử dụng mảng cho DSLK đơn thì làm thế nào ạ?
Bạn xem bài 12 nhá.
strcmp(x,” “) nghĩa là sao vậy anh !!
Nghĩa là so sánh x vs dấu cách.
a cho em hỏi là e chạy trên code block mà nó không dừng phần nhập phần tử thì lỗi ở đâu ạ. cứ chạy mãi nhập phần tử thứ …
Bạn xem điều kiện dừng là gì thì dựa vào đó thôi
cho em hỏi ở trên tại sao lúc thì dùng ” List” lúc thì dùng “NODE* ” . 2 cái này có khác nhau gì không ?
List là mình ám chỉ 1 danh sách, NODE* mình ám chỉ 1 con trỏ kiểu NODE. Dù nó bản chất giống nhau nhưng ta dùng thế naod là do mình.
Cũng như *a, *b. Ta có thể dùng a như 1 mảng 1 chiều, còn b là con trỏ kiểu int.
Anh Quân ơi mình muốn nhập ví dụ như danh sách họ tên thì làm thế nào ạ?
Bạn định nghĩa lại cái item là struct chứ không phải int là đk.
Cho em hỏi là ngay phần 8. Trong điều kiện lập while có p != NULL, vậy em có thể đảo while thành do while với điều kiện p->next != NULL, vì dữ liệu đầu vô là không cho danh sách rỗng.
Mình ko có phần nào nói là ds ko rỗng nên bạn cần xem xét kỹ. Còn code thì vẫn đk nếu bạn đảm bảo như bạn nói
em không hiểu chỗ tìm phần tử có giá trị x ạ?
Bạn không hiểu như thế nào…
Cho em hỏi ở phần 7 , sau khi thực hiện thì con trỏ L của mình sẽ bị dịch chuyển vậy mình có thể tạo một | node * q=L; sau khi thực hiện chèn thì mình trả lại L=q được không?
Bạn có thể nếu muốn
cho em hỏi tại sao ở hàm Make_node anh đã cho P->Next = Null rồi mà ở hàm Chèn node anh vẫn cho P->Next= L ( mà L = NULL) vậy anh? 2 cái này khác nhau chỗ nào vậy
L là list của mình mà. Nó có null đâu bạn?
Dạ vâng e hiểu rồi ạ e còn 1 thắc mắc nữa ở hàm Insert_k a có viết là :
while (Q != NULL && i != k-1) //duyet den vi tri k-1
{
i++;
Q = Q->next;
}
P->next = Q->next;
Q->next = P;
tức là duyệt đến khi nào Q-> next = null ms thôi, mà P->next ở hàm make_node thì = NULL sẵn rồi thì mình có thể bỏ dòng P->next=Q-> next và cho Q->next=P luôn đc ko a?
Ko. Bạn nhùn kỹ còn điều kiện i!=k-1 nữa. Q->next chưa chắc khác null
Cho em hỏi là tại sao 2 hàm xóa (phần 9,10) thì không dùng lệnh delete luôn. Theo em hiểu thì 2 phần đó mới chỉ loại bỏ node khỏi danh sách thôi, chứ node đó vẫn còn tồn tại trong bộ nhớ (do là kiểu con trỏ)?
Lệnh delete là lệnh nào bạn.
e nghĩ là bạn ấy muốn giải phóng bộ nhớ ấy, như có 1 bạn phía trên có đóng góp ý. :))
nhân tiện cho e hỏi sao cái này e copy nguồn về chạy trên vs 10 thì lúc nhập lại k đc nhỉ, nó báo lỗi: “The variable ‘P’ is being used without being initialized.” Hình như là do chưa khởi tạo giá trị, nhưng trong cái bài dslk kép của a thì lại k bị s… em k biết bị s nữa :(( hoang mang quá. mong a xem lại thử giùm e, em cảm ơn :]]
Mình không dùng vs nên ko rõ tại sao nữa.
E chào a, bài viết của a rất hay nhưng e co một thăvs mắc là trong phần khởi tạo danh sách rỗng, l là con trỏ rồi thì sao lại dùng tham chiếu để làm gì ạ ,e cảm ơn ạ
Để khi ra khỏi hàm thì L có thể thay đổi được. Nếu ko dùng tham chiếu thì trong hàm phải dùng *L = null
e van chua hieu lam a, khi minh truyen con tro thi khi ra khoi ham no van co the thay doi dc dung khong a?
Ukn nhưng đây là mình có con trỏ của con trỏ
vâng e cảm ơn ạ
Cho em hỏi ở phần 5, tạo 1 node thì toán tử * trước tên hàm có tác dụng gì vậy ạ.
Thank anh trước
Nó có nghĩa là trả về 1 con trỏ
Bạn ơi. Cho mình hỏi chút. Mình có tách riêng từng phần trong code của bạn. Cụ thể là mình tách phần danh sách rỗng, khi nhập xong các phần tử và nhập 0 để kết thúc nhưng nó không in ra các phần tử đã nhập. Vậy muốn in ra phần tử đã nhập thì làm thế nào bạn. Thank bạn
Mình chưa hiểu ý bạn lắm. Bên trên mình cũng chia ra các hàm như vậy mà
bạn ơi,cho mình hỏi,sao chương chình mình chay không được vậy,hi
Bạn có thể gửi cho mình lỗi ko?
khi mình chạy chương trình của bạn, nó hiện lên là:nhập phần tử thứ 1,xong mình nhập vào thì chương trình kêu nhập phần tử thứ 2,cứ riết vậy,không dừng lại được,bạn giúp mình nha,hi
Bạn xem lại điều kiện dừng nhé. Đến khi nào nhập số 0 thì dừng.
Cho em hỏi cái [Warning] ‘typedef’ was ignored in this declaration [enable by default]. Có ảnh hưởng gì đến chương trình không vậy a ?
Tại sao khi ta cấp phát vùng nhớ cho P thì không thể sử dụng được và báo lỗi còn nếu ta bỏ nó vào Insert_first và Insert_k thì ok
vd: Node *Make_Node (Node *P, item x) //tao 1 Node P chua thong tin la x
{
P = (Node *) malloc (sizeof (Node)); //Cap phat vung nho cho P
P->next = NULL; //Cho truong Next tro den NULL
P->Data = x; //Ghi du lieu vao Data
return P;
}
void Insert_first (List &L, item x) //Chen x vao vi tri dau tien trong danh sach
{
Node *P;
P = Make_Node(P,x); //tao 1 Node P
P->next = L; //Cho P tro den L
L = P; //L tro ve P
}
void Insert_k (List &L, item x, int k) //chen x vao vi tri k trong danh sach
{
Node *P, *Q = L;
int i=1;
if (k len(L)+1) printf(“Vi tri chen khong hop le !”); //kiem tra dieu kien
else
{
P = Make_Node(P,x); //tao 1 Node P
if (k == 1) Insert_first(L,x); //chen vao vi tri dau tien
else //chen vao k != 1
{
while (Q != NULL && i != k-1) //duyet den vi tri k-1
{
i++;
Q = Q->next;
}
P->next = Q->next;
Q->next = P;
}
}
}——-> Khong chạy được !
còn nếu:
void Insert_first (List &L, item x) //Chen x vao vi tri dau tien trong danh sach
{
Node *P;
P = (Node *) malloc (sizeof (Node)); //Cap phat vung nho cho P
P->next = NULL; //Cho truong Next tro den NULL
P->Data = x; //Ghi du lieu vao Data
P->next = L; //Cho P tro den L
L = P; //L tro ve P
}
void Insert_k (List &L, item x, int k) //chen x vao vi tri k trong danh sach
{
Node *P, *Q = L;
int i=1;
if (k len(L)+1) printf(“Vi tri chen khong hop le !”); //kiem tra dieu kien
else
{
P = (Node *) malloc (sizeof (Node)); //Cap phat vung nho cho P
P->next = NULL; //Cho truong Next tro den NULL
P->Data = x; //Ghi du lieu vao Data
if (k == 1) Insert_first(L,x); //chen vao vi tri dau tien
else //chen vao k != 1
{
while (Q != NULL && i != k-1) //duyet den vi tri k-1
{
i++;
Q = Q->next;
}
P->next = Q->next;
Q->next = P;
}
}
}————>thì ok chạy được
Mong Anh vui lòng giải thích.
thanks you !
Ah, mình hiểu ý tưởng của bạn, tuy nhiên mình chưa rõ lỗi do đâu, có thể do code bạn cú pháp lỗi cũng có thể do cách làm lỗi. Nên chưa giải thích được cho bạn.
phần khai báo Data sao mình không cho luôn là : int Data hả a ?!!
Để sau này mình thay đổi kiểu dữ liệu một cách linh hoạt
nếu như Item là một kiểu dữ liệu struct thì các hàm trên thay đổi như thế nào ạ? nhất là cái hàm tìm kiếm đó a
anh có bài về danh sách liên kết của pascal k?
hinh nhu ko :3
em không hiểu hàm kiểm tra rỗng cho lắm anh có thể giải thích cho em được không Ạ ?
Phép so sánh L == NULL sẽ trả về đúng (1) sai (0). Do vậy nó chứa giá trị luôn và ta có thể return luôn nó.
Xin lỗi nhưng bạn làm sai rồi ~~ bị bug rồi
Cảm ơn bạn, bạn vui lòng cho mình biết lỗi ở đâu và như thế nào được không. Mình sẽ sửa lại nếu thực sự lỗi. 🙂
Em ko hỉu chỗ nhập dữ liệu cho danh sách a giải thích lại giúp e dk ko
Em cảm ơn
Nhập dữ liệu thì là mình nhập các giá trị cho danh sách thôi
HÌnh như phần 1 dòng 7 có vấn đề:
typedef Node *List;
Nếu viết như trên thì cả cấu trúc node sẽ được định nghĩa là kiểu “*List”, dấu * lúc này sẽ chỉ đóng vai trò như là một ký tự của xâu “*List”. Như vậy phải mang cả string “*List” đi để định nghĩa các phần tử khác.
//Nếu sai thì mong thông cảm :))
Dấu * đó có nghĩa là con trỏ chứ không phải là chuỗi nhé.
Anh có chú thích L = NULL là cho L trỏ đến NULL;
// Vậy tại sao in địa chỉ của L printf(“%d”,L); thì nó lại ra 0(NULL) ạ ? Vậy NULL là địa chỉ của L, hay là nơi mà nó trỏ tới. :/
mà đề nghị anh, viết C thì thuần C chứ đừng có lôi C++ vào kết hợp mà không chú thích, em hơi bị bức xúc rồi đấy ạ
Trong bài viết mình có nói là từ bài 13 mình sẽ code lẫn một chút cho đơn giản mà.
Anh ơi chỗ cấp phát vùng nhớ anh sử dụng malloc, em đang viết bằng C#, anh biết hàm nào thay thế cho malloc ko ạ ?
bạn có thể dùng calloc xem sao. mà C# thì đâu cần malloc hay calloc nhỉ?
cho mình hỏi ở phần cài đặt danh sách ý nếu viết theo code c chuẩn thì viết ntn ạ? Tại mình đang học về lt c chuẩn thôi nên k đc viết theo c++ .Mong anh quân viết giùm mình code với
Viết C chuẩn thì các hàm không có & mà dùng * để biểu thị nó là con trỏ. Khi gọi hàm thì dùng &.
VD xây dựng hàm hoán vị
void hoanVi(int *a, int *b)
…
Gọi hàm: hoanVi(&x, &y);
A quân hiểu sai ý mình r. Mình muốn hỏi ở cái phần đầu ý, lúc cài đặt ds thì viết code c kiểu g. Bởi vì khi mình cop hết và chạy trên devc thì nó bị lỗi ở lệnh typedef node *list. a quân có sửa đc lỗi này khi chạy trên c đc k
Muốn sửa mình cần biết nó báo lỗi gì mới sửa được 🙂
Ad ơi k có code cho mấy cái hàm trao đổi hay sẵp xếp node à ad?
Ah phần đó không có nhé.
Anh cho em hỏi đoạn code này
typedef struct Node //Xay dung mot Node trong danh sach
{
item Data; //Du lieu co kieu item
Node *next; //Truong next la con tro, tro den 1 Node tiep theo
};
Đoạn này nếu code ngôn ngư C(file.c) sẽ báo lỗi “không biết Node là gì ở đoạn Node *Next ”
Còn ở C++(file.cpp) thì chạy bình thường đúng ko ạ ? Anh có thể chỉ em cách fix để có thể chạy được trên C dc ko ?
Trong C thì bạn cho thêm struct vào trước nhé.
struct Node *next;
Cảm ơn anh !
Rất tuyệt vời! Cảm ơn anh rất nhiều
Tuy nhiên, có cách nào xóa trực tiếp một phần tử có giá trị x mà không cần gọi đệ quy như cách anh giới thiệu không?
Không e nhé. Hoặc đến thời điểm này thì mình không biết 🙂
anh ơi trong các hàm trên hàm liên quan đến giá trị x tại sao có hàm dùng int &x, có hàm là int x vậy ạ. Khi nào thì dùng kiêu tham chiếu & ạ??
Khi muốn giữ lại giá trị của x sau khi ra khỏi hàm nhé.
anh cho em hỏi chút về phần sắp xếp theo code của anh với ạ!. em có thử nhưng chưa thành công, em tham khảo thì phần lớn là code dùng con trỏ trỏ đến head và tail, áp dụng vào bài anh em không biết viết như nào, mong được anh giúp đỡ!. cám ơn anh nhiều!
Em cứ coi nó là mảng ý. Mảng thì cần a[i] và a[j] để so sánh, đổi chỗ. Nhưng đây thì biến nó thành 2 con trỏ p và q tương ứng a[i], a[j]. Việc đổi chỗ thì e cắt và trỏ lại các liên kết phù hợp là được.
cho mình hỏi là hàm nhập vào nếu là 0 thì nó sẽ dừng vậy giờ nếu muốn nhập 0 vào thì sao ạ?
Thì bạn cho 1 điều kiện khác. VD nhập vào 1 số âm nào đó thì dừng…
Chào anh,
Anh cho em hỏi vì sao trong hàm tạo một nút (Node *Make_Node) anh lại sử dụng kiểu khai báo con trỏ hàm? Việc khai báo như vậy nhằm mục đích gì? Và có thể viết hàm đó như một hàm bình thường đc ko?
Vì muốn hàm đó trả về 1 con trỏ nên viết như vậy. Giống như hàm muốn trả về kiểu nguyên thì là int ham() vậy.
ad ơi cho em hỏi em cần làm 1 chương trình c với yêu cầu là nhập vào 1 file văn bản và xuất ra tất cả các kí tự của file đó kèm theo vị trí của file đó trong đoạn văn bản , những chữ nào trùng nhau thì chỉ cần đưa ra vị trí dòng bao nhiêu và đứng thứ mấy của dòng đó ..
a quân cho em hỏi ứng dụng của danh sách liên kết đơn và danh sách liên kết kép với ạ. e thấy stack thường dùng bằng DSLK đơn, còn queue thường dùng DSLK kép. Nếu dùng queue dễ truy cập vậy sao vẫn phải dùng stack ạ. cám ơn a!
Vì queue và stack có những ứng dụng khác nhau.
Anh Quân cho em hỏi ạ
Mục chèn phần tử x vào vị trí k, code của anh Quân chỉ cần chia 2 trường hợp: chèn giữa, chèn đầu danh sách
Nhưng theo em tìm hiểu, như trong tài liệu của PTIT, họ chia 3 trường hợp: chèn đầu, chèn giữa, chèn cuối danh sách
Nên dùng cách nào vậy anh Quân ?
Cách nào cũng được nhé.
Dạ e chào a. Thưa a e đang gặp rắc rối về bài này. E đã làm nhưng nó chỉ xuất ra đc 1 sinh viên . Còn lại mấy câu khác k chạy đc. Mong a giúp e.
Sử dụng cấu trúc danh sách liên kết đơn để định nghĩa 1 danh sách lưu trữ 1 danh sách sinh viên.
Thông tin sv bao gồm mssv, HoTen, Diem , XLoai
A) viết hàm nhập 1 dssv từ bàn phím
B) viết hàm in ra màn hình dssv
C) viết hàm tìm kiếm 1 sv có mssv đc nhập từ bàn phím. Nếu tìm thấy trả ra địa chỉ của nút đó. Ngược lại trả ra NULL
D) viết hàm xóa khỏi ds 1 sv có mssv đc nhập từ bàn phím
E) viết hàm bổ sung 1 sv mới vào sau phần tử có địa chỉ trả ra ở câu D
F) viết hàm bổ sung 1 sv mới vào trước phần tử có địa chỉ trả ra ở câu D
G) tạo 1 menu cho phép lựa chọn thực hiện các côg việc trên
Chào anh! Anh cho e hỏi về đoạn code phía trên của anh với.
1. Khởi tạo danh sách L = NULL
– Hỏi tại sao ko phải gán L->next = NULL mà là L = NULL.
2. Chèn node P vào đầu danh sách L, giả sử L = NULL
– Hỏi lúc này P đang trỏ đến NULL hay P->next trỏ đến NULL.
Cảm ơn anh.
1. L là danh sách thì khởi tạo danh sách phải dùng L = null chứ, L->next = NULL là phần tử tiếp theo bằng NULL mất rồi còn đâu.
2. P->next trỏ tới NULL nhé, Vì P đang có giá trị rồi.
chào anh, a có thể bày cho e bài này được không ạ làm đến đoạn này thì em bí:
Cho biết SV có điểm trung bình thấp nhất trong số các SV xếp loại giỏi.
Em cảm ơn
Em tìm những sinh viên nào có điểm > X nhưng là nhỏ nhất là được nhé. X là điểm để xếp loại giỏi.
viết hàm tính số nút của danh sách liên kết bằng phuong pháp đệ qui ạ
cho em hỏi tại sao lại có các danh sách lien kết đơn,đôi ,vòng
Mỗi cái nó nhằm 1 mục đích khác nhau. Bạn có thể lên mạng tham khảo thêm