3.1 KHÁI NIỆM DANH SÁCH TUYẾN TÍNHĐịnh nghĩa các phép toán tác động vào danh sách Khởi tạo danh sách rỗng creat Kiểm tra danh sách rỗng empty Kiểm tra danh sách đầy full Bổ sung
Trang 1CHƯƠNG 3
DANH SÁCH TUYẾN TÍNH
Trang 2NỘI DUNG
Khái niệm danh sách tuyến tính
Lưu trữ kế tiếp của danh sách tuyến tính
Danh sách móc nối
Ngăn xếp
Hàng đợi
Trang 33.1 KHÁI NIỆM DANH SÁCH TUYẾN TÍNH
Danh sách là một dãy các phần tử thuộc cùng một lớp đối tượng nào đó gọi là kiểu phần tử
Ví dụ : Danh sách số nguyên, danh sách sinh viên,
Trong danh sách mối quan hệ lân cận giữa các phần tử được thể hiện gọi là danh sách tuyến tính
Danh sách tuyến tính hoặc rỗng hoặc có dạng
L = { a 1 , a 2 , , a n }
Trang 43.1 KHÁI NIỆM DANH SÁCH TUYẾN TÍNH
Danh sách tuyến tính hoặc rỗng hoặc có dạng
L = { a 1 , a 2 , , a n } Trong đó
n>0 thì a1 là phần tử đầu danh sách, an là phần tử cuối danh sách
ai là phần tử thứ i trong danh sách với (1<=i<=n)
ai được gọi là đứng trước ai+1 với (1<=i<n)
a được gọi là đứng sau a với (1<i<=n)
Trang 53.1 KHÁI NIỆM DANH SÁCH TUYẾN TÍNH
Định nghĩa các phép toán tác động vào danh sách
Khởi tạo danh sách rỗng (creat)
Kiểm tra danh sách rỗng (empty)
Kiểm tra danh sách đầy (full)
Bổ sung một phần tử vào danh sách (insert)
Loại bỏ một phần tử khỏi danh sách (del)
Sắp xếp danh sách (sort)
Tìm kiếm trên danh sách (search)
Tách danh sách hoặc ghép danh sách
Trang 63.2 LƯU TRỮ KẾ TIẾP CỦA DSTT
Khái niệm
Định nghĩa và khai báo CTDL
Định nghĩa các phép toán và chương trình thực hiện các phép toán cơ bản
Trang 73.2.1 Khái niệm
Sử dụng mảng một chiều làm cấu trúc lưu trữ danh sách
Mỗi phần tử của mảng lưu trữ một phần tử của danh sách, các phần tử của danh sách nằm kế tiếp nhau trong bộ nhớ
Ưu điểm
Truy cập trực tiếp tới các phần tử
Các thao tác được thực hiện khá đơn giản
Trang 83.2.2 Định nghĩa và khai báo CTDL
Giả sử các phần tử của danh sách có kiểu dữ liệu là
<kiểu phần tử>
Độ dài của danh sách là một số nguyên dương n
Danh sách được biểu diễn bởi một bản ghi gồm có hai trường
Trường thứ nhất: Là một số nguyên biểu diễn số phần tử có trong danh sách
Trường thứ hai : Là mảng một chiều có kích thước đủ lớn để lưu các phần tử của danh sách
Trang 93.2.2 Định nghĩa và khai báo CTDL
Khai báo cấu trúc dữ liệu :
Trang 103.2.3 Các phép toán cơ bản
Khởi tạo danh sách rỗng (creat)
Kiểm tra danh sách rỗng (empty)
Kiểm tra danh sách đầy (full)
Bổ sung một phần tử vào danh sách (insert)
Loại bỏ một phần tử khỏi danh sách (del)
Trang 113.2.3 Các phép toán cơ bản
Khởi tạo danh sách rỗng
void creat(list &l)
{
l.sopt = 0;
}
Trang 133.2.3 Các phép toán cơ bản
Kiểm tra danh sách đầy
int full(list l)
{ return l.sopt ==max;
}
Trang 163.2.3 Các phép toán cơ bản
sách l
void insert (<kiểu phần tử> x, int k, list &l)
{ if (l.sopt <max && k>=0 && k <= l.sopt )
{ for (int i = l.sopt; i >k; i )
Trang 183.2.3 Các phép toán cơ bản
Phép loại bỏ một phần tử khỏi danh sách
void del(int k, list &l)
{
if (k>=0 && k < l.sopt) { l.sopt ;
for (int i=k; i<l.sopt; i++)
l.ptu[i] = l.ptu[i +1];
}
}
Trang 203.3.1 Danh sách móc nối đơn
Định nghĩa và khai báo CTDL
Định nghĩa các phép toán và chương trình thực hiện các phép toán cơ bản
Trang 21Định nghĩa và khai báo CTDL
Mỗi phần tử của danh sách là một bản ghi gồm có 2 trường
data chứa thông tin của phần tử
next là một con trỏ,trỏ vào nút đứng sau trong danh
sách
Trang 22Định nghĩa và khai báo CTDL
Danh sách được định nghĩa là một con trỏ trỏ vào phần
tử đầu tiên của danh sách
Con trỏ next của phần tử cuối trong danh sách nhận giá trị NULL báo hiệu kết thúc danh sách
l
Trang 23Định nghĩa và khai báo CTDL
Khai báo cấu trúc như sau :
struct node
{ <kiểu phần tử> ptu;
node *next;
} *l ;
Trang 24Các phép toán cơ bản
Khởi tạo danh sách rỗng (creat)
Kiểm tra danh sách rỗng (empty)
Bổ sung một phần tử vào danh sách (insert)
Loại bỏ một phần tử khỏi danh sách (del)
Trang 25Các phép toán cơ bản
Khởi tạo danh sách rỗng
void creat(node *&l)
{
l = NULL;
}
Trang 28Các phép toán cơ bản
Bổ sung phần tử x vào sau con trỏ p trong danh sách
móc nối đơn l
void insert(<kiểu phần tử> x, node *p, node *&l)
{ node *q=new node;
q->ptu = x;
q->next = p->next;
p->next = q;
}
Trang 31p->next = q->next;
delete q;
}
Trang 323.3.2 Danh sách móc nối vòng
Định nghĩa và khai báo CTDL
Định nghĩa các phép toán
Trang 33Định nghĩa và khai báo CTDL
(Tương tự như danh sách móc nối đơn)
Mỗi phần tử của danh sách là một bản ghi gồm có 2 trường
data chứa thông tin của phần tử
next là một con trỏ,trỏ vào nút đứng sau trong danh
sách
Trang 34Định nghĩa và khai báo CTDL
Danh sách được định nghĩa là một con trỏ trỏ vào phần
tử đầu tiên của danh sách
Con trỏ next của phần tử cuối trong danh sách thay
vì nhận giá trị NULL lại trỏ vào phần tử đầu danh sách tạo ra mối nối vòng
l
Trang 35Định nghĩa và khai báo CTDL
Khai báo cấu trúc như sau :
(Tương tự như danh sách móc nối đơn)
struct node
{ <kiểu phần tử> ptu;
node *next;
} *l ;
Trang 36Các phép toán cơ bản
Khởi tạo danh sách rỗng (creat)
Kiểm tra danh sách rỗng (empty)
Bổ sung một phần tử vào danh sách (insert)
Loại bỏ một phần tử khỏi danh sách (del)
Trang 37 Sử dụng nút đầu danh sách đánh dấu vị trí đầu khi truy nhập
Nút đầu danh sách lưu giá trị đặc biệt không lưu giá trị phần tử cần lưu giữ
Trang 383.3.3 Danh sách móc nối kép
Định nghĩa và khai báo CTDL
Định nghĩa các phép toán và chương trình thực hiện các phép toán cơ bản
Trang 39Định nghĩa và khai báo CTDL
Mỗi phần tử của danh sách móc nối kép là một bản ghi gồm có 3 trường
data chứa thông tin của phần tử
next là một con trỏ trỏ vào nút đứng sau trong danh
Trang 40Định nghĩa và khai báo CTDL
Danh sách được định nghĩa là hai con trỏ trỏ vào phần
tử đầu tiên và phần tử cuối cùng của danh sách
Con trỏ pre của phần tử đầu trong danh sách nhận giá trị NULL báo hiệu nút đầu danh sách
Con trỏ next của phần tử cuối trong danh sách nhận giá trị NULL báo hiệu kết thúc danh sách
NULL
Trang 41Định nghĩa và khai báo CTDL
Khai báo cấu trúc như sau :
Trang 42Các phép toán cơ bản
Khởi tạo danh sách rỗng (creat)
Kiểm tra danh sách rỗng (empty)
Bổ sung một phần tử vào danh sách (insert)
Loại bỏ một phần tử khỏi danh sách (del)
Trang 43Các phép toán cơ bản
Khởi tạo danh sách rỗng
void creat(list &ds)
{
ds.l = NULL;
}
Trang 45q
NULL
Trang 46Các phép toán cơ bản
Bổ sung phần tử x vào sau con trỏ p trong danh sách
móc nối kép
void insert(<kiểu phần tử> x, node *p, list &ds)
{ node *q=new node; q->ptu = x;
q->next = p->next; q->pre=p;
if (p->next!=NULL) p->next->pre=q;
else ds.r=q;
p->next = q;
}
Trang 47q
NULL NULL
Trang 50Ưu nhược điểm của danh sách móc nối
Ưu điểm
Tận dụng được không gian nhớ rỗi trong bộ nhớ, không cần
khai báo dự phòng cần đến đâu xin cấp phát đến đó, không sử dụng có thể giải phóng biến động thu hồi bộ nhớ
Không phải dãn hoặc dồn danh sách khi chèn thêm hoặc loại bỏ phần tử khỏi danh sách mà chỉ cần thay đổi mối nối liên kết
Nhược điểm
Không truy nhập trực tiếp vào các phần tử của danh sách
Mỗi phần tử ngoài các byte nhớ để lưu dữ liệu cần phải lưu
thêm con trỏ liên kết các phần tử trong danh sách
Trang 51BÀI TẬP ỨNG DỤNG
Bài 1
Thông tin của mỗi sinh viên bao gồm masv(xâu),
hoten(xâu), dtb(thực)
Thực hiện các yêu cầu sau đối với danh sách mảng,
danh sách móc nối đơn, danh sách móc nối kép lưu các phần tử là các sinh viên
Trang 52 Chèn một sinh viên có thông tin nhập từ bàn phím
vào đầu danh sách
Chèn một sinh viên có thông tin nhập từ bàn phím
vào cuối danh sách
Trang 53BÀI TẬP ÁP DỤNG
Bài 1 (tiếp)
Chèn một sinh viên có thông tin nhập từ bàn phím vào danh sách đã sắp xếp thỏa mãn thứ tự sắp xếp
Loại các sinh viên có mã trùng nhau trong danh sách
Ghép hai danh sách sinh viên đã sắp xếp theo thứ tự tăng dần (giảm dần) của dtb thành một danh sách
được sắp xếp
Đảo chiều danh sách móc nối đơn
Trang 54BÀI TẬP ỨNG DỤNG
Bài 2
Mỗi số hạng của đa thức được biểu diễn bởi hệ số
(nguyên) và số mũ (nguyên) Yêu cầu :
Tạo cấu trúc danh sách móc nối vòng có đầu lưu các
số hạng của đa thức
Nhập đa thức p(x), q(x) với nút đầu có hệ số là 0, số
mũ là -1
Hiện các số hạng của đa thức p(x), q(x)
Cộng đa thức p(x) vào đa thức q(x)
Hiện đa thức q(x)
Trang 55DANH SÁCH MÓC NỐI ĐƠN
#include <stdio.h>
#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <alloc.h> #include <iomanip.h>
struct svien
{char masv[10];
char hten[20];
float dtb;
};
Trang 56DANH SÁCH MÓC NỐI ĐƠN
struct dssv
{svien ptu;
dssv *next;
}*l;
void nhap(dssv *&l);
void hien(dssv *l);
void sxep(dssv *&l);
void main()
{clrscr();
nhap(l); hien(l); cout<<"\nDANH SACH SAU KHI SAP XEP"; sxep(l); hien(l); getch();
Trang 57DANH SÁCH MÓC NỐI ĐƠN
void nhap(dssv *&l)
{dssv *q;
char s[10];
l=new dssv; q=l;
cout<< "nhap ma sv : ";
gets(l->ptu.masv);
cout<<"Nhap ho ten :";
gets(l->ptu.hten);
cout<<"nhap dtb :";
cin>>l->ptu.dtb;
cout<< "nhap ma sv : ";
while(strcmp(s,"")) {q->next=new dssv; q=q->next;
strcpy(q->ptu.masv,s);
cout<<"Nhap ho ten :";
gets(q->ptu.hten);
cout<<"nhap dtb :";
cin>>q->ptu.dtb;
cout<< "nhap ma sv : ";
gets(s);
}
q->next=NULL;
}
Trang 58DANH SÁCH MÓC NỐI ĐƠN
void hien(dssv *l) { while(l!=NULL)
{ cout<<l->ptu.masv<<setw(20)<<l->ptu.hten;
cout<<setw(10)<<l->ptu.dtb<<“\n”; l=l->next; }
}
Trang 59DANH SÁCH MÓC NỐI ĐƠN
void sxep(dssv *&l)
{dssv *p,*q; svien tg;
if (l!=NULL)
{p=l;
while (p->next!=NULL)
{q=p->next;
while (q!=NULL)
{if (p->ptu.dtb<q->ptu.dtb)
{tg=q->ptu;q->ptu=p->ptu;p->ptu=tg;}
q=q->next;
}
p=p->next;
}
}