Bài giảng Lập trình C - Chương 2: Ngôn ngữ C - Con trỏ (Pointer)
Nội dung
1. Đặt vấnđề -ctdl động, tại sao?
2. Con trỏvà kiểu dữliệuđộng
3. Cấu trúc và con trỏ
4. Danh sách liên kết
5. Sắp xếp trên danh sách
Tóm tắt nội dung Bài giảng Lập trình C - Chương 2: Ngôn ngữ C - Con trỏ (Pointer), để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
Tập giá trị [-32768, 32767]
Tập các thao tác: +, -, *, /, %
Kiểu con trỏ (của 1 kiểu dữ liệu T) cũng vậy gồm:
Tập giá trị là tập địa chỉ của kiểu dữ liệu T tương ứng
Tập thao tác: tạo con trỏ đến đối tượng có kiểu T
Ví dụ: con trỏ số nguyên được khai báo như sau
int *p;
// có kích thước cố định 2 hay 4 byte tùy vào NNLT, loại con trỏ
//Con trỏ kiểu int thì có thể lưu được địa chỉ của biến kiểu int.
9/16/2008 T.P.Tuấn - LTC 10
Biến động
Không được khai báo tường minh
Có thể được cấp pháp hoặc giải phóng bộ nhớ khi người sử dụng
yêu cầu.
Các biến này không theo quy tắc phạm vi (tĩnh)
Vùng nhớ của biến được cấp phát trong Heap.
Kích thước có thể thay đổi trong quá trình sống
Con trỏ làm nhiệm vụ quản lý các biến này bằng cách lưu địa chỉ
vùng nhớ của chúng.
Ví dụ:
int *p,*q;
p=new int; //xin cấp phát vùng nhớ kiểu int
q=new int[10]; //xin cấp phát 10 vùng kiểu int
…. //sử dụng các biến động ở đây
delete p; //trả lại vùng nhớ cho hệ thống
delete [ ]q; //trả lại vùng nhớ cho hệ thống
2. Con trỏ và kiểu dữ liệu động
Biến động
9/16/2008 T.P.Tuấn - LTC 11
2. Con trỏ và kiểu dữ liệu động
9/16/2008 T.P.Tuấn - LTC 12
2. Con trỏ và kiểu dữ liệu động
9/16/2008 T.P.Tuấn - LTC 13
2. Con trỏ và kiểu dữ liệu động
9/16/2008 T.P.Tuấn - LTC 14
2. Con trỏ và kiểu dữ liệu động
9/16/2008 T.P.Tuấn - LTC 15
2. Con trỏ và kiểu dữ liệu động
int x;
int *p, *q;
p=&x;
q=&x;
9/16/2008 T.P.Tuấn - LTC 16
2. Con trỏ và kiểu dữ liệu động
9/16/2008 T.P.Tuấn - LTC 17
2. Con trỏ và kiểu dữ liệu động
9/16/2008 T.P.Tuấn - LTC 18
2. Con trỏ và kiểu dữ liệu động
9/16/2008 T.P.Tuấn - LTC 19
2. Con trỏ và kiểu dữ liệu động
Ví dụ về việc xin cấp phát biến động:
#include
void main()
{
int *p;
p=new int; //xin cấp phát 1 vùng nhớ
*p=4;
printf(“Gia tri cua vung nho do p quan ly: %d”, *p);
delete p; //trả lại vùng nhớ sau khi đã sử dụng xong
}
9/16/2008 T.P.Tuấn - LTC 20
3. Cấu trúc và con trỏ
#include
typedef struct PHANSO
{
int tu, mau;
}PHANSO;
void main()
{
PHANSO x;
x.tu=3;x.mau=8;
printf(“%d/%d”,x.tu,x.mau);
PHANSO *a;
a=new PHANSO;
a->tu=5; // (*a).tu=5;
a->mau=7; // (*a).mau=7;
printf(“Phan so: %d/%d”,a->tu,a->mau);
delete a;
}
9/16/2008 T.P.Tuấn - LTC 21
4. Danh sách liên kết
Mảng là một hình thức liên kết ngầm
Các phần tử trong mảng được cấp phát vùng
nhớ một cách liên tiếp nhau
Với T là kiểu dữ liệu cho trước, xét mảng các
phần tử kiểu T. Ta có:
Address(i)=Address(0)+(i-1)*sizeoof(T).
20459
43210
9/16/2008 T.P.Tuấn - LTC 22
4. Danh sách liên kết
Có nhiều loại danh sách liên kiết như:
Danh sách liên kết đơn
Danh sách liên kết kép
Danh sách liên kết vòng
….
Trong môn này ta tìm hiểu kỹ về danh
sách liên kết đơn
9/16/2008 T.P.Tuấn - LTC 23
4. Danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 24
4. Danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 25
4. Danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 26
4. Danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 27
4. Danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 28
4. Danh sách liên kết đơn
Tạo danh sách
Khai báo danh sách liên kết
Khởi tạo danh sách liên kết
Tạo mới một phần tử để thêm vào danh sách liên kết
Thêm vào đầu danh sách
Thêm vào cuối danh sách
Xuất dữ liệu của toàn bộ danh sách liên kết
Thêm vào sau một phần tử cho trước
Tìm kiếm
Tìm một phần tử có khóa cho trước
Tìm một phần tử đứng trước một phần tử cho trước
Hủy danh sách
Hủy một phần tử đầu danh sách
Hủy một phần tử cuối danh sách
Hủy một phần tử sau một phần tử cho trước
Hủy một phần tử có khóa cho trước
Hủy toàn bộ danh sách
9/16/2008 T.P.Tuấn - LTC 29
4. Danh sách liên kết đơn
typedef struct NODE
{
int data; // 2 byte (dos)
NODE* next; // 2 byte (dos)
}NODE;
typedef struct LIST
{
NODE* pHead;
NODE* pTail;
}LIST;
Khai báo danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 30
4. Danh sách liên kết đơn
void KhoiTao(LIST &l)
{
l.pHead=NULL;
l.pTail=NULL;
}
Khởi tạo danh sách liên kết
Việc khởi tạo danh sách liên kết nhằm xác định
danh sách ban đầu mới tạo ra là rỗng
9/16/2008 T.P.Tuấn - LTC 31
4. Danh sách liên kết đơn
NODE* GetNode(int x)
{
NODE* p;
p=new NODE;
p->next=NULL;
p->data=x;
return p;
}
Tạo mới một phần tử để thêm vào danh sách
9/16/2008 T.P.Tuấn - LTC 32
4. Danh sách liên kết đơn
Thêm một phần tử vào đầu danh sách liên kết
1. Danh sách rỗng
2. Danh sách đã có phần tử
9/16/2008 T.P.Tuấn - LTC 33
4. Danh sách liên kết đơn
void AddHead(LIST &l, NODE* add)
{
if(l.pHead==NULL)
{
l.pHead=l.pTail=add;
}
else
{
add->next=l.pHead;
l.pHead=add;
}
}
Thêm một phần tử vào đầu danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 34
4. Danh sách liên kết đơn
Thêm một phần tử vào cuối danh sách liên kết
1. Danh sách rỗng
2. Danh sách đã có phần tử
9/16/2008 T.P.Tuấn - LTC 35
4. Danh sách liên kết đơn
void AddTail(LIST &l, NODE* add)
{
if(l.pHead==NULL)
{
l.pHead=l.pTail=add;
}
else
{
l.pTail->next=add;
l.pTail=add;
}
}
Thêm một phần tử vào cuối danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 36
4. Danh sách liên kết đơn
void PrintfList(LIST l)
{
NODE* p;
p=l.pHead;
while(p!=NULL)
{
printf(“-->%d”,p->data);
p=p->next;
}
}
Xuất dữ liệu của danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 37
4. Danh sách liên kết đơn
Thêm một phần tử vào sau một phần tử cho trước
1. Danh sách rỗng
2. Danh sách đã có phần tử
q
9/16/2008 T.P.Tuấn - LTC 38
4. Danh sách liên kết đơn
void AddAfter(LIST &l, NODE* q, NODE* add)
{
if(q!=NULL)
{
add->next=q->next;
q->next=add;
if(q==l.pTail)
l.pTail=add;
}
else
{
AddHead(l,add);
}
}
Thêm một phần tử vào sau một phần tử cho trước
9/16/2008 T.P.Tuấn - LTC 39
4. Danh sách liên kết đơn
Tìm một phần tử trong danh sách liên kết khi biết khóa (data)
Sử dụng 1 con trỏ phụ p để duyệt tất cả
các phần tử trong danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 40
4. Danh sách liên kết đơn
NODE* Search(LIST l, int data)
{
NODE* p=l.pHead;
while((p!=NULL) && (p->data!=data))
p=p->next;
return p;
}
Tìm một phần tử trong danh sách liên kết khi biết khóa (data)
Kết quả trả về là NULL tức là không tìm thấy phần tử có khóa data
Ngược lại nếu tìm thấy thì nó sẽ trả về địa chỉ của phần tử đầu tiên
có khóa data trong danh sách liên kết.
9/16/2008 T.P.Tuấn - LTC 41
4. Danh sách liên kết đơn
NODE* SearchPre(LIST l, NODE* s)
{
NODE* p=l.pHead;
while((p!=NULL) && (p->next!=s))
p=p->next;
return p;
}
Tìm một phần tử đứng trước một phần tử cho trước
9/16/2008 T.P.Tuấn - LTC 42
4. Danh sách liên kết đơn
Hủy phần tử đầu trong danh sách liên kết
1. Tách phần tử đầu ra khỏi danh sách
2. Xóa phần tử này
9/16/2008 T.P.Tuấn - LTC 43
4. Danh sách liên kết đơn
void RemoveHead(LIST &l)
{
if(l.pHead!=NULL)
{
p=l.pHead;
l.pHead=l.pHead->next;
delete p;
if(l.pHead==NULL)
l.pTail=NULL;
}
}
Hủy phần tử đầu trong danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 44
4. Danh sách liên kết đơn
Hủy phần tử cuối trong danh sách liên kết
1. Tách phần tử cuối ra khỏi danh sách
2. Gán pTail = địa chỉ của phần tử kế cuối
3. Xóa phần tử này
9/16/2008 T.P.Tuấn - LTC 45
4. Danh sách liên kết đơn
void RemoveTail(LIST &l)
{
if(l.pHead==NULL)
return;
NODE *p=l.pTail;
l.pTail=SearchPre(l,l.pTail);
delete p;
if(l.pTail!=NULL)
l.pTail->next=NULL;
else
l.pHead=NULL;
}
Hủy phần tử cuối trong danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 46
4. Danh sách liên kết đơn
Hủy phần tử sau phần tử q trong danh sách liên kết
1. Tách phần tử p ra khỏi danh sách liên kết
2. Xóa phần tử này
q
9/16/2008 T.P.Tuấn - LTC 47
4. Danh sách liên kết đơn
void RemoveAfter(LIST &l, NODE* q)
{
NODE* p;
if(q!=NULL)
{
p=q->next;
if(p!=NULL)
{
if(p==l.pTail)
l.pTail=q;
q->next=p->next;
delete p;
}
}
else
RemoveHead(l);
}
Hủy phần tử sau phần tử q trong danh sách liên kết
Lưu ý: q là phần tử trong
danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 48
4. Danh sách liên kết đơn
Hủy phần tử có khóa k cho trước
1. Tìm phần tử p có khóa k và phần tử q trước nó
2. Tách phần tử p ra khỏi danh sách liên kết
3. Xóa nó
q
K=39
9/16/2008 T.P.Tuấn - LTC 49
4. Danh sách liên kết đơn
void Remove (LIST &l, int k)
{
NODE* p=l.pHead,*q=NULL;
while((p!=NULL)&&(p->data!=k))
{
q=p; p=p->next;
}
if(p==NULL) return;
if(q!=NULL)
{
if(p==l.pTail)
{
l.pTail=q;
l.pTail->next=NULL;
}
q->next=p->next;
delete p;
}
else // p là phần tử đầu tiên (pHead)
RemoveHead(l);
}
Hủy phần tử có khóa k cho trước
9/16/2008 T.P.Tuấn - LTC 50
4. Danh sách liên kết đơn
Cách 1:
void RemoveList (LIST &l, int k)
{
while(l.pHead!=NULL)
RemoveHead(l);
}
Cách 2:
void RemoveList (LIST &l)
{
while(l.pHead!=NULL)
{
p=l.pHead;
l.pHead=l.pHead->next;
delete p;
}
l.pTail=NULL;
}
Hủy toàn bộ danh sách liên kết
9/16/2008 T.P.Tuấn - LTC 51
5. Sắp xếp trên danh sách liên kết
void ListSelectionSort (LIST &l)
{
NODE* min; //trỏ đến pt có data min
NODE* i,*j;
for(i = l.pHead;i->next!=NULL;i=i->next)
{
min=i;
for(j=i->next;j!=NULL;j=j->next)
if(j->datadata)
min=j;
HoanVi(min->data,i->data);
}
}
Selection Sort – Hoán vị nội dung phần dữ liệu (data)
9/16/2008 T.P.Tuấn - LTC 52
5. Sắp xếp trên danh sách liên kết
void ListSelectionSort (LIST &l)
{
NODE *i,*j,*min, *minpre=NULL;
LIST lresult;KhoiTao(lresult);
while(l.pHead!=NULL) //danh dách chưa hết
{
min=l.pHead;minpre=NULL;
for(j=min,i=min->next;i!=NULL;j=i,i=i->next)
if(i->datadata)
{
min=i;
minpre=j;
}
if(minpre==NULL)
{
l.pHead=l.pHead->next;if(min==l.pTail) l.pTail=NULL;
}
else
{
if(min==l.pTail) l.pTail=minpre;minpre->next=min->next;
}
min->next=NULL;
AddTail(lresult,min);
}
l=lresult;
}
Selection Sort – Thay đổi mối liên kết
1. Tìm pt min có data nhỏ nhất
2. Tách min ra khỏi danh sách
3. Thêm min vào đầu ds mới
9/16/2008 T.P.Tuấn - LTC 53
File đính kèm:
Bài giảng Lập trình C - Chương 2 Ngôn ngữ C - Con trỏ - Pointer.pdf

