Tải bản đầy đủ (.pdf) (20 trang)

Các thao tác trên danh sách liên kết đơn

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (217.98 KB, 20 trang )

Trang
1
GV: Trần Minh Thái

CÁC THAO TÁC TRÊN DANH SÁCH LIÊN KẾT ĐƠN
struct tNODE
{
<KIỄU DỮ LIỆU DANH SÁCH> Key;
struct tNODE *pNext;
};
typedef struct tNODE NODE;
struct tList
{
NODE *pHead, *pTail;
};
typedef struct tList LIST;

1. Tìm kiếm
2. Duyệt
3. Đếm
4. Kiểm tra
5. Thêm
6. Xóa
7. Sắp xếp

1. Tìm kiếm

1.1. Tìm phần tử có giá trị x
(SV tự vẽ hình minh họa)













Trang
2
GV: Trần Minh Thái

- Đầu vào: DSLK đơn l, giá trị x
- Kết quả: Trả về con trỏ tìm được (hoặc NULL: Nếu không có x)
- Giải thuật:
B1: p trỏ vào đầu danh sách
B2: Nếu p = NULL thì trả về NULL. Kết thúc
Ngược lại sang B3
B3: Nếu giá trị p = x thì trả về p. Kết thúc
B4: p trỏ đến phần tử kế tiếp, quay lại B2
- Cài đặt (Giả sử tìm phần tử có giá trị
x trên danh sách số nguyên):
NODE *TimX(LIST l, int x)
{
NODE *p=l.pHead;
while(p)
{
if(p->Key==x)

return p;
p=p->pNext;
}
return NULL;
}

1.2. Tìm phần tử có giá trị max / min
(SV tự vẽ hình minh họa)












- Đầu vào: DSLK đơn l
- Kết quả: Trả về con tr
ỏ max tìm được
- Giải thuật:
B1: pMax trỏ vào đầu danh sách
p trỏ vào sau pMax
B2: Nếu p = NULL thì trả về pMax. Kết thúc
Trang
3
GV: Trần Minh Thái


Ngược lại sang B3
B3: Nếu giá trị p > giá trị pMax thì gán pMax = p
B4: p trỏ đến phần tử kế tiếp quay lại B2
- Cài đặt (Giả sử tìm max trên danh sách số nguyên):
NODE *TimMax(LIST l)
{
NODE *pMax=l.pHead, *p=pMax->pNext;
while(p)
{
if(p->Key>pMax->Key)
pMax = p;
p=p->pNext;
}
return pMax;
}

1.3. Tìm phần tử có giá trị thỏa điều kiện xuất hiện đầu tiên
(Giả sử phần tử có giá trị chẵn xuất hiện đầu tiên trên danh sách số nguyên)
(SV tự vẽ hình minh họa)














- Đầu vào: DSLK đơn l
- Kết quả: Trả về con trỏ chứa giá trị chẵn đầu tiên tìm được (hoặc NULL: Nếu
không có chẵn)
- Giải thuật:
B1: p trỏ vào đầu danh sách
B2: Nếu p = NULL thì trả về NULL. Kết thúc
Ngược lại sang B3
B3: Nếu giá trị p là chẵn thì trả về p. Kết thúc
B4: p trỏ
đến phần tử kế tiếp, quay lại B2
- Cài đặt:
Trang
4
GV: Trần Minh Thái

NODE *TimChanDau(LIST l)
{
NODE *p=l.pHead;
while(p)
{
if(p->Key%2==0)
return p;
p=p->pNext;
}
return NULL;
}


1.4. Tìm phần tử có giá trị thỏa điều kiện xuất hiện cuối cùng
(Giả sử phần tử có giá trị chẵn xuất hiện cuối cùng trên danh sách số nguyên)
(SV tự vẽ hình minh họa)













- Đầu vào: DSLK đơn l
- Kết quả: Trả về con trỏ chứa giá trị chẵn xuất hiện cuối cùng (hoặc NULL: Nếu
không có chẵn)
- Giải thuật:
B1: p trỏ vào đầu danh sách
pChanCuoi=NULL;
B2: Nếu p = NULL thì trả về pChanCuoi. Kết thúc
Ngược lại sang B3
B3: Nếu giá trị p là chẵn thì gán pChanCuoi = p
B4: p trỏ đến ph
ần tử kế tiếp, quay lại B2
- Cài đặt:
NODE *TimChanCuoi(LIST l)
{

NODE *p=l.pHead, *pChanCuoi=NULL;
Trang
5
GV: Trần Minh Thái

while(p)
{
if(p->Key%2==0)
pChanCuoi=p;
p=p->pNext;
}
return pChanCuoi;
}

1.5. Tìm phần tử có giá trị max (min) thỏa điều kiện cho trước
(Giả sử tìm phần tử có giá trị chẵn lớn nhất trên danh sách số nguyên)
(SV tự vẽ hình minh họa)














- Đầu vào: DSLK đơn l
- Kết quả: Trả về con trỏ chứa giá trị chẵn lớn nhất (hoặc NULL: Nếu không có
chẵn)
- Giải thuật:
B1: pMaxChan là phần tử chẵn đầu tiên của danh sách
Nếu không có chẵn trả về NULL. Kết thúc
B2: p trỏ vào sau pMaxChan
B3: Nếu p trỏ đến NULL thì trả về pMaxChan. Kết thúc
Ngược lại sang B4

B4: Nếu giá trị của p là chẵn và lớn hơn giá trị pMaxChan thì
Gán pMaxChan = p
B5: p trỏ đến phần tử kế tiếp, quay lại B3
- Cài đặt:
NODE *TimMaxChan(LIST l)
{
NODE *pMaxChan=TimChanDau(l), *p;
if(pMaxChan==NULL)
Trang
6
GV: Trần Minh Thái

return NULL;
p=pMaxChan->pNext;
while(p)
{
if(p->Key%2==0&&p->Key>pMaxChan->Key)
pMaxChan=p;
p=p->pNext;
}

return pMaxChan;
}

1.6. Tìm phần tử đứng trước phần tử p cho trước
(SV tự vẽ hình minh họa)












- Đầu vào: DSLK đơn l, phần tử
p
- Kết quả: Trả về con trỏ đứng trước phần tử p (hoặc NULL: Nếu không có)
- Giải thuật:
*Trường hợp 1: Nếu p trỏ vào đầu danh sách thì trả về NULL
*Trường hợp 2: Ngược lại trường hợp 1
B1: pTruoc trỏ và đầu danh sách
B2: Trong khi pTruoc trỏ đến phần tử kế chưa bằng p thì
Dời pTruoc sang phần tử kế tiếp
B3: Trả về
pTruoc. Kết thúc
- Cài đặt:
NODE *TimNodeTruocp(LIST l, NODE *p)

{
if(p==l.pHead)
return NULL;
NODE *pTruoc=l.pHead;
Trang
7
GV: Trần Minh Thái

while(pTruoc->pNext!=p)
pTruoc=pTruoc->pNext;
return pTruoc;
}

2. Duyệt

2.1. Xuất danh sách
(SV tự vẽ hình minh họa)











- Đầu vào: DSLK đơn l
- Kết quả: In giá trị các phần tử của danh sách ra màn hình

-
Giải thuật:
B1: p trỏ và đầu danh sách
B2: Nếu p = NULL thì kết thúc
Ngược lại In giá trị p
B3: p trỏ đến phần tử kế tiếp, quay lại B2
- Cài đặt: (Giả sử l là danh sách số nguyên)
void Xuat(LIST l)
{
NODE *p=l.pHead;
while(p)
{
printf(“%d->”, p->Key);
p=p->pNext;
}
}

2.2. Xuất danh sách thỏa điều kiện cho trước
(SV tự vẽ hình minh họa)


Trang
8
GV: Trần Minh Thái












- Đầu vào: DSLK đơn l
- Kết quả: In giá trị các phần tử của danh sách thỏa điều kiện ra màn hình
- Giải thuật:
B1: p trỏ vào đầu danh sách
B2: Nếu p = NULL thì k
ết thúc
B3: Nếu giá trị của p thỏa điều kiện thì in giá trị p
B4: p trỏ đến phần tử kế tiếp, quay lại B2
- Cài đặt: (Giả sử xuất các giá trị có giá trị chẵn trong danh sách số nguyên)
void XuatChan(LIST l)
{
NODE *p=l.pHead;
while(p)
{
if(p->Key%2==0)
printf(“%d->”, p->Key);
p=p->pNext;
}
}

3. Đếm

3.1. Đếm số phần tử
(SV tự vẽ hình minh họa)










Trang
9
GV: Trần Minh Thái




- Đầu vào: DSLK đơn l
- Kết quả: Trả về số lượng các phần tử trong danh sách
- Giải thuật:
B1: d=0
p trỏ vào đầu danh sách
B2: Nếu p = NULL thì trả về d. Kết thúc
B3: d=d+1
B4: p trỏ đến phần tử kế tiếp, quay lại B2
- Cài đặt:
int SoLuongNode(LIST l)
{
int d=0;
NODE *p=l.pHead;
while(p)
{

d++;
p=p->pNext;
}
return d;
}

3.2. Đếm số phần tử thỏa điều kiện
(SV tự vẽ hình minh họa)












- Đầu vào: DSLK đơn l, đi
ều kiện bên ngoài (nếu có: ví dụ giá trị x để so sánh)
- Kết quả: Trả về số lượng các phần tử thỏa điều kiện trong danh sách
- Giải thuật:
Trang
10
GV: Trần Minh Thái

B1: d=0
p trỏ vào đầu danh sách

B2: Nếu p = NULL thì trả về d. Kết thúc
B3: Nếu giá trị p thỏa điều kiện thì
d=d+1
B4: p trỏ đến phần tử kế tiếp, quay lại B2
- Cài đặt (Giả sử đếm số lượng phần tử có giá trị chẵn trong danh sách số nguyên):
int SoLuongNodeChan(LIST l)
{
int d=0;
NODE *p=l.pHead;
while(p)
{
if(p->Key%2==0)
d++;
p=p->pNext;
}
return d;
}

4. Kiểm tra

4.1. Kiểm tra tồn tại một phần tử thỏa mãn điều kiện cho trước
(SV tự vẽ hình minh họa)













-
Đầu vào: DSLK đơn l, điều kiện bên ngoài (nếu có: ví dụ giá trị x để so sánh)
- Kết quả: Trả về 1 nếu thỏa điều kiện, ngược lại trả về 0
- Giải thuật:
B1: p trỏ vào đầu danh sách
B2: Nếu p = NULL thì trả về 0. Kết thúc
B3: Nếu giá trị p thỏa điều kiện thì
Trang
11
GV: Trần Minh Thái

Trả về 1. Kết thúc
B4: p trỏ đến phần tử kế tiếp, quay lại B2
- Cài đặt (Giả sử kiểm tra xem danh sách có tồn tại phần tử có giá trị lẻ trong danh
sách số nguyên):
int KiemTraTonTaiLe(LIST l)
{
NODE *p=l.pHead;
while(p)
{
if(p->Key%2!=0)
return 1;
p=p->pNext;
}
return 0;
}


4.2. Kiểm tra toàn bộ các phần tử thỏa mãn điều kiện cho trước
- Đầu vào: DSLK đơn l, điều kiện bên ngoài (nếu có: ví dụ giá trị x để so sánh)
- Kết quả: Trả về 1 nếu thỏa điều kiện, ngược lại trả về 0
- Giải thuật:
B1: p trỏ vào đầu danh sách
B2: Nếu p = NULL thì trả về 1. Kết thúc
B3: Nếu giá trị
p KHÔNG thỏa điều kiện thì
Trả về 0. Kết thúc
B4: p trỏ đến phần tử kế tiếp, quay lại B2
- Cài đặt (Giả sử kiểm tra xem toàn bộ các phần tử trong danh sách đều có giá trị
chẵn trên danh sách số nguyên):
int KiemTraToanChan(LIST l)
{
NODE *p=l.pHead;
while(p)
{
if(p->Key%2!=0)
return 0;
p=p->pNext;
}
return 1;
}
- Cài đặt (Giả sử kiểm tra xem danh sách số nguyên có tăng dần hay không):
int KiemTraTang(LIST l)
{
Trang
12
GV: Trần Minh Thái


NODE *p=l.pHead;
while(p!=l.pTail)
{
if(p->Key > (p->pNext)->Key)
return 0;
p=p->pNext;
}
return 1;
}

5. Thêm

5.1. Thêm phần tử vào đầu danh sách
(SV tự vẽ hình minh họa)












- Đầu vào: DSLK đơn l, phần tử p cần thêm
- Kết qu
ả: DSLK đơn l sau khi thêm

- Giải thuật:
*Trường hợp 1: Nếu l rỗng thì
Con trỏ đầu và cuối của danh sách = p
*Trường hợp 2: (l khác rỗng)
B1: p trỏ kế tiếp vào đầu danh sách
B2: Gán con trỏ đầu = p
- Cài đặt:
void ThemDau(LIST &l, NODE *p)
{
if(l.pHead==NULL)
l.pHead=l.pTail=p;
else
{
p->pNext = l.pHead;
Trang
13
GV: Trần Minh Thái

l.pHead = p;
}
}

5.2. Thêm phần tử vào cuối danh sách
(SV tự vẽ hình minh họa)













- Đầu vào: DSLK đơn l, phần tử p cần thêm
- Kết qu
ả: DSLK đơn l sau khi thêm
- Giải thuật:
*Trường hợp 1: Nếu l rỗng thì
Con trỏ đầu và cuối của danh sách = p
*Trường hợp 2: (l khác rỗng)
B1: Con trỏ cuối của danh sách trỏ kế tiếp vào p
B2: Gán con trỏ cuối = p
- Cài đặt:
void ThemCuoi(LIST &l, NODE *p)
{
if(l.pHead==NULL)
l.pHead=l.pTail=p;
else
{
l.pTail->pNext =p;
l.pTail = p;
}
}


5.3. Thêm phần tử vào sau một phần tử cho trước
(SV tự vẽ hình minh họa)

Trang
14
GV: Trần Minh Thái













- Đầu vào: DSLK đơn l, phần tử k cần thêm và phần tử p
- Kết quả: DSLK đơn l sau khi thêm k sau p
- Giải thuật:
*Trườ
ng hợp 1: Nếu p là con trỏ cuối của danh sách thì
Thêm k vào cuối danh sách l
*Trường hợp 2: (p khác con trỏ cuối)
B1: pSau là con trỏ đứng sau p
B2: Cho p trỏ tới k
B3: Cho k trỏ tới pSau
- Cài đặt:
void ThemkSaup(LIST &l, NODE *p, NODE *k)
{
if(p==l.pTail)

ThemCuoi(l, k);
else
{
NODE *pSau = p->pNext;
p->pNext = k;
k->pNext = pSau;
}
}
5.4. Thêm phần tử k vào trước một phần tử p cho trước
(SV tự vẽ hình minh họa)






Trang
15
GV: Trần Minh Thái







- Đầu vào: DSLK đơn l, phần tử k cần thêm và phần tử p
- Kết quả: DSLK đơn l sau khi thêm k trước p
- Giải thuật:
B1: Thêm k vào sau p

B2: Hoán vị giá trị của p và k
- Cài đặt:
void ThemkTruocp(LIST &l, NODE *p, NODE *k)
{
ThemkSaup(l, p, k);
int tam = p->Key;
p->Key = k->Key;
k->Key = tam;
}

6. Xóa

6.1. Xóa phần tử đầu
(SV tự vẽ hình minh họa)












- Đầu vào: DSLK đơn l
- Kết quả: DSLK đơn l sau khi xóa phần t
ử đầu
- Giải thuật:

*Trường hợp 1: Nếu l rỗng thì kết thúc
*Trường hợp 2: (l khác rỗng)
B1: pXoa là con trỏ đầu của danh sách
Trang
16
GV: Trần Minh Thái

B2: Cho con trỏ đầu trỏ vào phần tử kế tiếp
B3: Xóa pXoa
B4: Nếu con trỏ đầu = NULL thì gán con trỏ cuối = NULL
- Cài đặt:
void XoaDau(LIST &l)
{
if(l.pHead!=NULL)
{
NODE *pXoa=l.pHead;
l.pHead=l.pHead->pNext;
delete pXoa;
if(l.pHead==NULL)//Trường hợp danh sách có 1 phần tử
l.pTail=NULL;
}
}

6.2. Xóa phần tử cuối
(SV tự vẽ hình minh họa)













- Đầu vào: DSLK đơn l
- Kết quả: DSLK đơn l sau khi xóa phần t
ử cuối
- Giải thuật:
*Trường hợp 1: Nếu l rỗng thì kết thúc
*Trường hợp 2: Nếu danh sách có một phần tử thì xóa đầu
Ngược lại:
B1: pTruoc là con trỏ đứng trước con trỏ cuối của danh sách
B2: Cho pTruoc trỏ kế tiếp tới NULL
B3: Xóa con trỏ cuối
B4: Gán con trỏ cuối là pTruoc
- Cài đặt:
Trang
17
GV: Trần Minh Thái

void XoaCuoi(LIST &l)
{
if(l.pHead!=NULL)
{
if(l.pHead==l.pTail)
XoaDau(l);
else

{
NODE *pTruoc=TimNodeTruocp(l, l.pTail);
pTruoc->pNext=NULL;
delete l.pTail;
l.pTail=pTruoc;
}
}
}

6.3. Xóa phần tử p cho trước
(SV tự vẽ hình minh họa)












- Đầu vào: DSLK đơn l, node p cần xóa
- Kết quả: DSLK đơn l sau khi xóa p
- Giải thuật:
*Trường hợp 1: Nếu p là con trỏ đầu thì xóa đầu
*Trường hợp 2: Nếu p là con trỏ cuối thì xóa cuối
Ngược lại:
B1: pTruoc là con trỏ đứng trước p

pSau là con trỏ đứng sau p
B2: Xóa p
B3: Cho pTruoc trỏ vào pSau
- Cài đặt:
Trang
18
GV: Trần Minh Thái

void Xoap(LIST &l, NODE *p)
{
if(p==l.pHead)
XoaDau(l);
else if(p==l.pTail)
XoaCuoi(l);
else
{
NODE *pTruoc=TimNodeTruocp(l, p);
NODE *pSau = p->pNext;
delete p;
pTruoc->pNext = pSau;
}
}

6.4. Xóa phần tử đứng trước phần tử cho trước
(SV tự vẽ hình minh họa)













- Đầu vào: DSLK đơn l, node p để xác đị
nh node cần xóa
- Kết quả: DSLK đơn l sau khi xóa trước phần tử p
- Giải thuật:
*Trường hợp 1: Nếu p là con trỏ đầu thì kết thúc
*Trường hợp 2: (p khác con trỏ đầu)
B1: pTruoc là con trỏ đứng trước p
B2: Xóa pTruoc
- Cài đặt:
void XoaTruocp(LIST &l, NODE *p)
{
if(p!=l.pHead)
{
Trang
19
GV: Trần Minh Thái

NODE *pTruoc=TimNodeTruocp(l, p);
Xoap(pTruoc);
}
}

6.5. Xóa phần tử đứng sau phần tử cho trước

(SV tự vẽ hình minh họa)












- Đầu vào: DSLK đơn l, node p để xác định node cầ
n xóa
- Kết quả: DSLK đơn l sau khi xóa phần tử sau p
- Giải thuật:
*Trường hợp 1: Nếu p là con trỏ cuối thì kết thúc
*Trường hợp 2: (p khác con trỏ cuối)
B1: pSau là con trỏ đứng sau p
B2: Xóa pSau
- Cài đặt:
void XoaSaup(LIST &l, NODE *p)
{
if(p!=l.pTail)
{
NODE *pSau=p->pNext;
Xoap(pSau);
}
}


6.6. Hủy toàn bộ danh sách
(SV tự vẽ hình minh họa)



Trang
20
GV: Trần Minh Thái










- Đầu vào: DSLK đơn l
- Kết quả: DSLK đơn l sau khi hủy (rỗng)
- Giải thuật:
Trong khi con trỏ đầu khác NULL thì xóa đầu
- Cài đặt:
void Huy(LIST &l)
{
while(l.pHead)
XoaDau(l);
}



×