Đồ án cấu trúc dữ liệu giải thuật tên đề tài đề tài số 01
Trang 1TRƯỜNG ĐẠI HỌC BÁCH KHOA KHOA CÔNG NGHỆ THÔNG TIN
ĐỒ ÁN CẤU TRÚC DỮ LIỆU & GIẢI
THUẬT
ĐỀ TÀI SỐ 01
Sinh viên thực hiện : Nguyễn Ngọc Thương
Trương Vũ Thùy Trang Lớp : 10T1LT
Đà Nẵng tháng 5/2011
Trang 2LỜI CẢM ƠN
Chúng em xin chân thành cám ơn thầy Phan Chí Tùng đã tận tình hướng
dẫn và giúp đỡ chúng em trong quá trình thực hiện đề tài này.
Chúng em xin cám ơn các bạn trong và ngoài lớp đã động viên, đóng góp ý kiến và hỗ trợ chúng em trong quá trình thực hiện đồ án.
Tuy nhiên do kinh nghiệm còn hạn chế và thời gian có hạn nên còn có nhiều thiếu sót rất mong được sự thông cảm và đóng góp ý kiến của quý thầy cô
và các bạn.
Chúng em xin chân thành cám ơn!
Đà Nẵng, tháng 5 năm 2011
Sinh viên thực hiện
Nguyễn Ngọc Thương – Trương Vũ Thùy Trang
Trang 3NHẬN XÉT CỦA GIÁO VIÊN HƯỚNG DẪN
SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang
Trang 4NHẬN XÉT CỦA GIÁO VIÊN PHẢN BIỆN
Trang 5
MỤC LỤC
GIỚI THIỆU ĐỀ TÀI 1
CẤU TRÚC DỮ LIỆU YÊU CẦU 2
I Cấu trúc dữ liệu 2
I.1 Giới thiệu sơ lược cấu trúc cây 2
I.2 Các khái niệm trong cây 3
I.2.1 Các nút 3
I.2.2 Nút gốc 3
I.2.3 Các nút lá 3
I.2.4 Các nút trong 3
I.2.5 Cây con 4
I.3 Biểu diễn cây 4
I.3.1 Biểu diễn bằng các nút với các con trỏ 4
I.3.2 Biểu diễn cây nhị phân bằng mảng 4
I.4 Các phương pháp duyệt cây 5
II Chương trình 5
II.1 Các thư viện sử dụng trong chương trình: 5
II.2 Định nghĩa các cấu trúc dữ liệu 5
II 3 Các hàm sử dụng trong chương trình chính 6
II.4 Hình ảnh chạy chương trình: 6
II.5 Mã nguồn chương trình: 7
SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang
Trang 6CHƯƠNG I
GIỚI THIỆU ĐỀ TÀI
Gia phả là cách ghi chép tên tuổi, tiểu sử, phần mộ, ngày giỗ của từng ngườitrong gia tộc, theo thứ tự các đời Gia phả đã xuất hiện từ thời xa xưa ở phương Tâycũng như ở phương Đông Nội dung của gia phả thường gồm hai phần: phần đầu ghichép nguồn gốc của dòng họ, đó là phần phả kí Tiếp theo là phần tộc hệ, lần lượt ghichép tên huý (tên tự, tên hiệu), ngày tháng năm sinh, năm mất, chức tước, phần mộ,ngày giỗ của từng người trong họ Ngoài ra, còn có phần kỉ sự, ghi chép sự nghiệp,công trạng của ông tổ các đời Để thấy rõ một cách tổng quát các chi lớn, nhỏ, xa, gầncủa một họ, người ta còn lập ra các phả đồ, với những hình vẽ đơn giản kèm theo têntuổi ghi vắn tắt ở bên dưới
Trong phạm vi đồ án này, chúng em xin xây dựng một chương trình nhỏ
để lưu trữ và hiển thị một cây gia phả đơn giản được biểu diễn dưới cấu trúc cây gồmcác chức năng:
+ Nhập một cây gia phả từ bàn phím
+ Hiển thị cây gia phả lên màn hình
+ Tìm kiếm một thành viên trong gia phả và hiển thị họ tên, ngàytháng năm sinh và tình trạng gia đình của con cháu, những người ngang hàng vớingười tìm thấy, và in ra gia phả của người này
Trang 7- Để giải quyết bài toán lưu trữ một cây gia phả của một dòng họ gồm các thông
tin : họ và tên, ngày tháng năm sinh và tình trạng gia đình (có hoặc chưa có gia đình)của từng thành viên ta có thể sử dụng cấu trúc cây n phân để lưu trữ
- Đối với kiểu cấu trúc này, rất phù hợp để biểu diễn sơ đồ phả hệ của dòng họmột cách minh bạch, rõ ràng trong tìm kiếm và thích hợp trong lưu trữ Điều khó khăn
ở đây là bậc của cây phụ thuộc vào số con lớn nhất của một thành viên trong gia tộc, vìthế khó có thể xác định trước được n trong lý thuyết
- Với gốc cây lưu trữ thông tin của ông tổ của dòng họ, các nhánh con là thông
tin của các thành viên ở các đời tiếp theo
Hình 1: Sơ đồ cây lưu giữ một gia phả.
I.1 Giới thiệu sơ lược cấu trúc cây
Trong khoa học máy tính, cây là một cấu trúc dữ liệu được sử dụng rộng rãi
gồm một tập hợp các nút (tiếng Anh: node) được liên kết với nhau theo quan hệ
cha-con Cây trong cấu trúc dữ liệu đầu tiên là mô phỏng (hay nói cách khác là sự saochép) của cây (có gốc) trong lý thuyết đồ thị Hầu như mọi khái niệm trong cây của lýthuyết đồ thị đều được thể hiện trong cấu trúc dữ liệu Tuy nhiên cây trong cấu trúc dữ
SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang 2
Trang 8liệu đã tìm được ứng dụng phong phú và hiệu quả trong nhiều giải thuật Khi phân tíchcác giải thuật trên cấu trúc dữ liệu cây, người ta vẫn thường vẽ ra các cây tương ứngtrong lý thuyết đồ thị.
dữ liệu phát triển từ trên xuống) Một nút có con được gọi là nút cha của các nút con.Một nút có nhiều nhất một nút cha
I.2.2 Nút gốc
Trong mỗi cây có một nút đặc biệt được gọi là nút gốc (hay nói đơn giản
là gốc) Nút gốc là nút duy nhất không có nút cha Nút gốc là nơi khởi đầu của nhiều
giải thuật trên cây Tất cả các nút khác được nối về nút gốc bằng một đường đi qua cáccạnh hay các liên kết
Trang 9I.2.5 Cây con
Một cây con là một bộ phận của cấu trúc dữ liệu cây mà tự nó cũng là một cây
Một nút bất kỳ trong cây T, cùng với các nút dưới nó tạo thành một cây con của T.
I.3 Biểu diễn cây
Có nhiều phương pháp biểu diễn cây Cách thường dùng nhất là biểu diễn mỗinút như một dữ liệu kiểu bản ghi, mỗi nút chứa các con trỏ tới các con hoặc cha của
nó, hoặc cả hai Cây cũng có thể biểu diễn bằng các mảng cùng với quan hệ giữa các
vị trí trong mảng
I.3.1 Biểu diễn bằng các nút với các con trỏ
Mỗi nút là một dữ liệu kiểu bản ghi với ba trường: Một trường thường gọi làINFOR, chứa thông tin lưu trữ tại nút đó Thông tin này có thể chỉ là một số, một ký
tự, cũng có thể là một tập hợp dữ liệu rất phức tạp Hai trường LLINK và RLINK chứacác liên kết trái và phải Nếu cây là cây nhị phân, LLINK trỏ tới con trái của nút,RLINK trỏ tới con phải của nút Nếu cây là cây tổng quát, LLINK trỏ tới con cực trái
và RLINK trỏ tới em kế cận phải của nút đó Do đó danh sách các nút biểu diễn mộtcây tổng quát, khi được xem là biểu diễn của cây nhị phân sẽ cho một cây nhị phân.Cây nhị phân này được gọi là cây nhị phân tương đương với cây tổng quát ban đầu
I.3.2 Biểu diễn cây nhị phân bằng mảng
Cây nhị phân đầy đủ là cây nhị phân, trong đó mỗi nút trong chỉ có hai con Câynhị phân hoàn chỉnh là cây nhị phân đầy đủ, trong đó tất cả các lá đều ở mức cao nhất.Một cây nhị phân hoàn chỉnh chiều cao h chỉ có 2h + 1 − 1 nút
Do đó người ta có thể dùng một mảng gồm 2h + 1 − 1 phần tử để biểu diễn câyhoàn chỉnh, bằng cách lần lượt lưu trữ thông tin của mỗi nút vào mảng theo thứ tự từ
trên xuống dưới, từ trái sang phải Khi đó con trái của nút thứ i là phần tử thứ 2*i, con phải là phần tử thứ 2*i+1 Cha của phần tử thứ i là phần tử thứ int(i/2).
Nếu cây là không hoàn chỉnh, ta gán giá trị Null cho các vị trí còn thiếu so vớicây nhị phân hoàn chỉnh Một cách khác, dùng một mảng hai chiều trong dòng thứ
SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang 4
Trang 10nhất ghi các thông tin của nút, dòng thứ hai ghi chỉ số của nút cha của nút đó với dấu +nếu nút hiện tại là con trái, với dấu - nếu nút hiện tại là con phải của nút cha.
I.4 Các phương pháp duyệt cây
Duyệt một cây là một trình tự làm việc với các nút trong cây, trình tự này giốngnhư một chuyến đi qua các nút trên cây theo các liên kết cha-con Các giải thuật duyệtkhác nhau về thứ tự “viếng thăm” giữa một nút cha và các nút con Chúng được gọi
là duỵệt tiền thứ tự, nếu viếng thăm đỉnh cha trước rồi mới đến các con, là duyệt hậu
thứ tự nếu viếng thăm hết các con rồi mới đến cha.
II Chương trình
II.1 Các thư viện sử dụng trong chương trình
- #include<conio.h> : Thư viện con trỏ màn hình
- #include<string.h> : Thư viện các hàm xử lý xâu chuổi
- #include<stdio.h> : Thư viện các hàm nhập xuất
II.2 Định nghĩa các cấu trúc dữ liệu
Để lưu trữ một gia phả, ta xây dựng một struct giapha để lưu các thôngtin sau:
- Họ tên , ngày tháng năm sinh , gia đình (đã kết hôn hay chưa)
- Số con : cho biết số con của người đó
- Mức : cho biết thế hệ của người đó tính từ ông trưởng (thế hệ 0).
- Biến con trỏ trỏ tới những người con khai báo thành mảng sub[n]
Trang 11Tree T;
Như vậy ta đã hoàn thành bước định nghĩa một cây tam phân để lưu dữ liệu củagia phả
II 3 Các hàm sử dụng trong chương trình chính
Chương trình bao gồm các hàm sau:
- Tree taogiapha(infor x,int ngay,int thang,int nam,int z,int socon,int Muc):
Hàm này trả vể giá trị là dữ liệu kiểu Tree, nhiệm vụ của hàm này là biến đổi từ thôngtin rời rạc gồm họ tên, ngày sinh , gia đình thành một phần tử kiểu bản ghi giapha
- void duyet(Tree T,Tree onggia,int *a): Hàm này duyệt cây theo thứ tự trước
Tức là duyệt theo thứ tự : Gốc Con1 Con2 Con3 Hàm duyệt qua tất cả cácphần tử của cây và in ra màn hình, hàm sử dụng trong hàm void hienthi(Tree T)
- void hienthi(Tree T): Hàm này để hiển thị toàn bộ cây ra màn hình.
- void Search(Tree T,infor x,Tree &vt ): Hàm này để tìm kiếm Người có tên “ x
“ lưu vào vùng nhớ Tree vt, nghĩa là tìm kiếm người đó và thông tin con cháu người
đó
- void SearchMuc(Tree T,int Muc,Tree vt): Hàm này để tìm thông tin tất cả
những người cùng thế hệ với người này
- void nhapnguoi(Tree &T): Hàm này để nhập thông tin của một người vào gia
phả từ bàn phím, gồm có : Họ tên , Ngày sinh , Gia đình ,Người sinh thành (cha)
- void hienthitimnguoi(): Hàm này hiển thị tất cả thông tin của những người
cùng thế hệ
II.4 Hình ảnh chạy chương trình
Hình 3 Menu của chương trình chính SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang 6
Trang 12Hình 4 Nhập thông tin một người vào gia phả
Hình 5 Sơ đồ cây gia phả của chương trình
Hình 6 Tìm kiếm thông tin một người trong gia phả
Trang 13II.5 Mã nguồn chương trình
Trang 14{
int i;
for(i=1;i<=socon;i++) (*p).sub[i]=NULL;
} (*p).muc=Muc;
return p;
}
void duyet(Tree T,Tree cha,int *a)
{ int Muc1,j;
Muc1=*a;
if(T!=NULL) {
cha=T;
j= (*T).muc;
switch(j) {
Trang 15SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang 10
Trang 16if(strcmp((*T).ht,x)==0) vt=T;
else { for(int i=1;i<=(*T).socon;i++) Search((*T).sub[i],x,vt);
} } }
void SearchMuc(Tree T,int Muc,Tree vt)
{ if(T!=NULL) {
if(((*T).muc==Muc)&&(T!=vt)) {
printf("\n\t\tTen: %s - Nam sinh: %d/%d/%d",(*T).ht,(*T).n,(*T).t,(*T).ns); if((*T).gd==1) printf("\t - Da ket hon");
else printf("\t - Chua ket hon");
} else { for(int i=1;i<=(*T).socon;i++) SearchMuc((*T).sub[i],Muc,vt);
} }
void nhapnguoi(Tree &T)
{ clrscr();
nhap:
fflush(stdin);
printf("\n Nhap ten: ");
gets(x);
Trang 17Search(T,x,vt);
if(vt!=NULL) {
printf("\n Nguoi nay da co trong gia pha.\n Nhap lai (An phim 1) - Bo qua (An phim 0): ");
scanf("%d",&boqua);
if(boqua) goto nhap;
else goto boqua;
} if(T!=NULL) {
printf("\n Khong tim thay ten nay.Vui long nhap lai.");
printf("\n Nhap lai (An phim 1) - Bo qua (An phim 0): ");
scanf("%d",&boqua);
if (boqua) goto lai;
else goto boqua;
} else if ((*vt).gd==0) {
printf("\n Nguoi nay chua ket hon nen chua co con.");
printf("\n Nhap lai (An phim 1) - Bo qua (An phim 0): ");
scanf("%d",&boqua);
if (boqua) goto lai;
else goto boqua;
}
SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang 12
Trang 18int i=1;
while((((*vt).sub[i])!=NULL)&&(i<=(*vt).socon)) i++;
if(i>(*vt).socon) {
printf("\n Nguoi nay chi co %d con, ko the them nua.",(*vt).socon);
printf("\n Nhap lai (An phim 1) - Bo qua (An phim 0): ");
scanf("%d",&boqua);
if(boqua) goto lai;
else goto boqua;
} } do { printf("\n Ngay sinh (1-31): ");
scanf("%d",&ngay);
} while (ngay<=0 || ngay>31);
do { printf("\n Thang sinh (1-12): ");
scanf("%d",&thang);
} while (thang<=0 || thang > 12);
nhapnam:
do { printf("\n Nam sinh(1900 - 2011): ");
scanf("%d",&nam);
} while (nam<1900 || nam>2011);
if(T!=NULL) {
if(nam <= (*vt).ns)
Trang 19{ printf ("\n Bo (me) cua %s la %s sinh nam %d, nam sinh cua %s phai lon hon
%d",x,(*vt).ht,(*vt).ns,x,(*vt).ns);
goto nhapnam;
} } if(T!=NULL) {
printf("\n Tinh trang gia dinh 1-Kethon / 0-Chuakethon :");
scanf("%d",&z);
} else z=1;
if(z!=0) { printf("\n Nhap so con: ");
scanf("%d",&socon);
} else socon=0;
if(T==NULL) {
while((((*vt).sub[i])!=NULL)&&(i<=(*vt).socon)) i++;
if(!(i>(*vt).socon)) {
Muc=(*vt).muc+1;
u=taogiapha(x,ngay,thang,nam,z,socon,Muc);
SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang 14
Trang 20printf("\n Them thong tin vao gia pha thanh cong.");
getch();
} } boqua:
}
void hienthitimnguoi()
{ fflush(stdin);
printf("\n Nhap ten nguoi ban muon tim: ");
gets(x);
vt=NULL;
Search(T,x,vt);
if(vt==NULL) {
printf("\n Khong tim thay %s trong gia pha",x);
getch();
} else { printf("\n Cac thong tin cua %s",x);
printf("\n\t - Tinh trang hon nhan cua nguoi nay: ");
if((*vt).gd) printf("Da ket hon");
else printf("Chua ket hon");
if((*vt).socon) {
printf("\n\t - Thong tin ve con cai:");
for(int k=1;k<=(*vt).socon;k++) if((*vt).sub[k]!=NULL)
printf("\n\t\t + Ten con: %s - Nam sinh: %d/%d/%d", (*((*vt).sub[k])).ht, (*((*vt).sub[k])).n,(*((*vt).sub[k])).t,(*((*vt).sub[k])).ns);
}
Trang 21else printf("\n\t\tNguoi nay khong co con");
printf("\n\t - Nhung nguoi cung the he trong gia pha:");
SearchMuc(T,(*vt).muc,vt);
getch();
clrscr();
printf("\n Cay gia pha cua %s:",x);
hienthi(vt,0);
} }
void thongtinnhom(){
printf("\n");
printf("\n**********************************************************");
printf("\n * *");
printf("\n * THONG TIN NHOM *");
printf("\n * Ho va ten Lop *");
printf("\n * *");
printf("\n * 1 Truong Vu Thuy Trang 10T1LT *");
printf("\n * 2 Nguyen Ngoc Thuong 10T1LT *");
printf("\n * *");
printf("\n***********************************************************"); } void main() { clrscr(); int i,cv; T=NULL; do { nhap: clrscr(); printf("\n"); printf("\n *************** DO AN MON CAU TRUC DU LIEU ****************"); SVTH: Nguyễn Ngọc Thương – Trương Vũ Thùy Trang 16
Trang 22printf("\n * ****** *");
printf("\n * THEM MOT NGUOI VAO GIA PHA : An phim 1 *");
printf("\n * HIEN THI CAY GIA PHA : An phim 2 *");
printf("\n * TIM MOT NGUOI TRONG GIA PHA : An phim 3 *");
printf("\n * XEM THONG TIN NHOM THUC HIEN : An phim 4 *");
printf("\n * THOAT CHUONG TRINH : An phim 0 *");
printf("\n**********************************************************"); printf("\n\n VUI LONG CHON CONG VIEC: ");
scanf("%d",&cv);
switch(cv) {
case 1:
nhapnguoi(T);
break;
case 2:
clrscr();
hienthi(T,0);
getch();
break;
case 3:
clrscr();
hienthitimnguoi();
getch();
break;
case 4:
thongtinnhom();
getch();
} }
while(cv!=0);
}