Tải bản đầy đủ (.doc) (21 trang)

Tiểu luận tìm cây phủ chiều ngang

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 (189.31 KB, 21 trang )

ĐẠI HỌC ĐÀ NẴNG
TRƯỜNG ĐẠI HỌC BÁCH KHOA ĐÀ NẴNG
------

TIỂU LUẬN
MÔN: TOÁN

ỨNG DỤNG

ĐỀ TÀI
THUẬT TOÁN TÌM CÂY PHỦ THEO CHIỀU
NGANG

GV hướng dẫn

: PGS.TSKH. Trần Quốc Chiến

Học viên

: Nguyễn Trọng Ân

Chuyên ngành

: Khoa Học Máy Tính

Khóa

: 30

ĐÀ NẴNG, 06/2015



LỜI MỞ ĐẦU
Lý thuyết đồ thị là một lĩnh vực nghiên cứu đã có từ lâu và có nhiều ứng
dụng trong ngành công nghệ thông tin. Những tư tưởng cơ bản của lý thuyết đồ thị
được đề xuất vào những năm đầu của thế kỷ 18 bởi nhà toán học lỗi lạc người Thụy
Sỹ: Leonhard Euler. Chính ông là người đã sử dụng đồ thị để giải bài toán nổi tiếng
về 7 cái cầu ở thành phố Konigberg.
Lý thuyết đồ thị có rất nhiều bài toán được ứng dụng có hiệu quả trong nhiều
lĩnh vực. Một trong những bài toán đó chính là bài toán tìm cây phủ của đồ thị.
Để ứng dụng phần lý thuyết đã học về Toán ứng dụng vào trong đề tài của
tiểu luận, em trình bày hai vấn đề :
 Thuật toán tìm cây phủ của đồ thị theo chiều ngang.
 Áp dụng thuật toán trên cho đồ thị không liên thông.
Em xin chân thành cảm ơn thầy PGS.TSKH. Trần Quốc Chiến đã hướng
dẫn và cung cấp kiến thức và tài liệu để em có thể hoàn thành tiểu luận này.

Học viên thực hiện
Nguyễn Trọng Ân


MỤC LỤC
LỜI MỞ ĐẦU........................................................................................................................2
CHƯƠNG I............................................................................................................................1
ĐẠI CƯƠNG VỀ ĐỒ THỊ.....................................................................................................1
CÂY........................................................................................................................................1
I.Định nghĩa............................................................................................................................1
1. Định nghĩa 1...................................................................................................................1
2. Định nghĩa 2...................................................................................................................1
3. Định nghĩa 3...................................................................................................................2
2

2
II.Tính chất.............................................................................................................................2
1. Định lý 1 (Định lý tương đương)...................................................................................2
2. Định lý 2.........................................................................................................................2
III.Cây m-phân.......................................................................................................................3
1. Định nghĩa......................................................................................................................3
2. Định lý 1.........................................................................................................................3
3. Hệ quả............................................................................................................................3
4. Định lý 2.........................................................................................................................3
CÂY PHỦ...............................................................................................................................3
I.Định nghĩa............................................................................................................................4
II.Định lý................................................................................................................................4
4
CHƯƠNG II...........................................................................................................................5
BÀI TOÁN TÌM CÂY PHỦ THEO CHIỀU NGANG..........................................................5
I.Giới thiệu bài toán................................................................................................................5
CHƯƠNG III..........................................................................................................................6
THIẾT KẾ VÀ CÀI ĐẶT BÀI TOÁN..................................................................................6
I.Thuật toán............................................................................................................................6
II.Thiết kế cấu trúc dữ liệu.....................................................................................................6
1.Dữ liệu đầu vào...................................................................................................................6
2.Dữ liệu đầu ra......................................................................................................................6
3.Hàng đợi Q..........................................................................................................................7
4.Cây phủ SpanningTree........................................................................................................7


III.Áp dụng thuật toán cho đồ thị không liên thông...............................................................8
1.Ý tưởng................................................................................................................................8
IV.Cài đặt bài toán..................................................................................................................8
KẾT LUẬN..........................................................................................................................16

TÀI LIỆU THAM KHẢO....................................................................................................17


CHƯƠNG I
ĐẠI CƯƠNG VỀ ĐỒ THỊ
CÂY
I.

Định nghĩa
1. Định nghĩa 1
Cây là đồ thị liên thông không chứa chu trình.

Ví dụ 3.1.1. Đồ thị sau là cây
v1

v2

v4

v3

v5

v6

v7

Gốc của cây là một đỉnh đặc biệt, thông thường là đỉnh trên cùng.
Mức của đỉnh là độ dài đường đi từ gốc lên đỉnh đó.
Độ cao của cây là mức lớn nhất của cây ( tức mức của đỉnh cách xa gốc nhất).

Trong ví dụ trên nếu ta chọn v1 là gốc thì v2, v3 là những định mức 1, các đỉnh v4, v5,
v6, v7 có mức 2, và độ cao của cây là 2

2. Định nghĩa 2
Cho T là cây có gốc v0 . Giả sử x, y, z là đỉnh của T và ( v0, v 1,…,vn) là
đường đi từ v0 đến vn trong T. khi đó ta gọi
Vn-1 là cha của vn
V0, …, vn-1 là tiền bối của vn
Vn là con của vn-1
1


y là hậu thế của x, nếu x là tiền bối của y
y và z là anh em nếu chúng đều là con của đỉnh x
x là đỉnh lá nếu nó không có con
x là đỉnh trong của cây nếu nó có con

3. Định nghĩa 3
Rừng là đồ thị mà mỗi thành phần liên thông là cây.
Ví dụ 3.1.2. Đồ thị sau là rừng có 3 cây

II.

Tính chất
1. Định lý 1 (Định lý tương đương)
Cho T là đồ thị n đỉnh. Các mệnh đề sau tương đương
T là cây.
T không chứa chu trình và có n-1 cạnh.
T liên thông và có n-1 cạnh.
T liên thông và mỗi cạnh là cầu.

Hai đỉnh bất kỳ được nối với nhau bởi một đường đi duy nhất.
T không chứa chu trình và nếu thêm một cạnh nối hai đỉnh thì ta thu được
đúng 1 chu trình
T liên thông và nếu them một cạnh nối hai đỉnh thì ta thu được đúng 1 chu
trình
2. Định lý 2
Tâm của cây là tập hợp hoặc chỉ có một đỉnh hoặc có hai đỉnh kề nhau.
2


III.

Cây m-phân

1. Định nghĩa
Cây m-phân ( m ∈ N*) là cây mà mọi đỉnh trong có tối đa m con và có ít nhất
một đỉnh có m con.
Cây m-phân đầy đủ là cây mà mọi đỉnh trong có đúng m con
Cây cân bằng là cây mà mọi đỉnh lá có mức là h hay h-1, trong đó h là chiều
cao của cây.

2. Định lý 1
Nếu cây m-phân đầy đủ có i là đỉnh trong, thì m.i+1 (=n) đỉnh.

3. Hệ quả
Cho T là cây m-phân đầy đủ có i là đỉnh trong, l là đỉnh lá và n là đỉnh. Khi
đó :
l = (m -1).i + 1
i=


& n=

i=

& l=

4. Định lý 2
Cho T là cây m-phân có l lá và chiều cao h. khi đó
Nếu T là cây m-phân cân bằng đầy đủ thì h= [logml]
Trong đó [x] (trần nguyên của x) ký hiệu số nguyên nhỏ nhất lớn hơn hoặc bằng
x.

CÂY PHỦ
3


I.

Định nghĩa
Cho đồ thị G=(V,E). Cho T gọi là cây phủ hay cây bao trùm của G,
nếu T là đồ thị con phủ của G.

Ví dụ: Các cây T1 và T2 là cây phủ của đồ thị G

G

II.

T1


T2

Định lý
Đồ thị G=(V,E) có cây phủ khi và chỉ khi G liên thông.

4


CHƯƠNG II
BÀI TOÁN TÌM CÂY PHỦ THEO CHIỀU
NGANG
I.

Giới thiệu bài toán
Cho một đồ thị bất kỳ, hãy tìm cây phủ của đồ thị. Đầu vào của bài toán là

tập các thông tin về số cạnh, số đỉnh cũng như các cạnh trong đồ thị. Đầu ra của bài
toán là tập các thông tin về số thành phần liên thông, các đinh cũng như các cạnh
phủ của từng đồ thị liên thông của đồ thị.

5


CHƯƠNG III
THIẾT KẾ VÀ CÀI ĐẶT BÀI TOÁN
I.

Thuật toán
Trong giải thuật này ta kí hiệu Q là hàng đợi (queue) các đỉnh, Ke(x) là danh


sách các đỉnh kề x.
Đầu vào: Đồ thị G=(V,E)
Đầu ra: Cây phủ T hoặc kết luận đồ thị không liển thong.
Các bước:
(1) Khởi tạo:
Chọn đỉnh Vi bất kỳ. Khởi tạo hàng đợi Q:=[Vi], T là đồ thị gồm 1 đỉnh Vi
và không có cạnh, Vi là gốc.
(2) Thêm cạnh:
Rút đỉnh x ∈ Q. Duyệt các đỉnh y ∈ Ke(x), nếu y ∉ T thì thêm cạnh (x,y) và
đỉnh y vào T và đẩy y vào hàng đợi Q.
Nếu Q ≠ ∅ và T chưa phủ hết các đỉnh, thì quay lại bước 2, ngược lại sang
bước 3.
(3) Kết luận:
Nếu T phủ hết các đỉnh của đồ thị, thì T là cây phủ, ngược lại đồ thị không
liên thông.

II.

Thiết kế cấu trúc dữ liệu
1.

Dữ liệu đầu vào
File dữ liệu đầu vào: GRAPH.INP có cấu trúc
n

m

(số đỉnh, số cạnh)

a1


b1

(đỉnh đầu, đỉnh cuối)

a2

b2



....

am bm

2.

Dữ liệu đầu ra
6


File kết quả: GRAPH.OUT
k

{số thành phần liên thông}

x1, ..., xi

{các đỉnh của thành phần liên thông thứ 1}


(u1, v1),(u2, v2), ...

{các cạnh cây phủ của thành phần liên thông thứ 1}

y1, ..., yj

{các đỉnh của thành phần liên thông thứ 2}

(r1, t1), (r2, t2), …

3.

{các cạnh cây phủ của thành phần liên thông thứ 2

Hàng đợi Q
typedef struct Queue
{
int capacity;
int size;
int front;
int rear;
int *elements;
}Queue;

Hàng đợi Queue có 5 thuộc tính:
-

Capacity: kiểu integer, chỉ số phần tử tối đa mà queue có thể chứa

-


Size: kiểu integer, chỉ số phần tử hiện tại mà queue chứa

-

Front: kiểu integer, chỉ vị trí phần tử đầu tiên của queue

-

Rear: kiểu integer, chỉ vị trí phần tử sau cùng của queue

4.

Cây phủ SpanningTree
typedef struct SpanningTree
{
int mT[MAX];
int mCountT;
int mSpanningEdges[MAX*2][2];
int mCountSpanningEdges;
}SpanningTree;

Cây phủ Cây phủ SpanningTree có 4 thuộc tính:
-

mT: kiểu mảng integer, chỉ tập hợp các đỉnh đã duyệt qua

-

mCount: kiểu integer, chỉ số phần tử của mảng mT

7


-

mSpanningEdges: kiểu mảng hai chiều integer, chỉ tập hợp các cạnh phủ đã

-

mCountSpanningEdges: kiểu integer, chỉ số phần tử của mảng
mSpanningEdges

Kết quả của bài toán là tập các cây phủ SpanningTree, nếu số phần tử của tập này
là 1 thì đồ thị có cây phủ, ngược lại lớn hơn 1, đồ thị không liên thông và tập này là
tập rừng phủ của đồ thị.

III.

Áp dụng thuật toán cho đồ thị không liên thông
1. Ý tưởng
Đối với bài toán đúng tức là đồ thị liên thông, khi duyệt hết các đỉnh và các
cạnh và hàng đợi Q rỗng, ta kiểm tra tập đỉnh trong T đã phủ đồ thị hết chưa
bằng cách so sánh số lượng phần tử của T(countT) và số đỉnh của đồ thị(n).
countT == n

Nếu đúng thì trả về true, tức là đồ thị liên thông và có tập phủ. Ngược lại, trả
về false, đồ thị không liên thông.
Nếu đồ thị không liên thông, ta đi tìm rừng phủ cho đồ thị theo các bước sau:
(1) Thêm tập T kết quả vào tập các cây phủ SpanningTree. Trong tập các
cạnh đầu vào của hàm tìm cây phủ, loại các cạnh chứa đỉnh đã tồn trong

tập T.
(2) Gọi hàm tìm cây phủ với tập các cạnh đầu vào mới có, nếu kết quả trả về
false, lặp lại bước 1, ngược lại sang bước 3.
(3) Thêm tập T kết quả vào tập các cây phủ SpanningTree. Kết thúc

IV.

Cài đặt bài toán

8


#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define MAX 20
typedef struct SpanningTree{
int mT[MAX];
int mCountT;
int mSpanningEdges[MAX*2][2];
int mCountSpanningEdges;
}SpanningTree;
void SpanningTreeToArray(SpanningTree ST[], int &countST, int T[], int countT, int
SpanningEdges[][2], int countSpanningEdges)
{
for(int i = 0; i < countT; i++){
ST[countST].mT[i] = T[i];
}
for(int i = 0; i < countSpanningEdges; i++){
for (int j = 0; j < 2; j ++ ){

ST[countST].mSpanningEdges[i][j] = SpanningEdges[i][j];
}
}
ST[countST].mCountT = countT;
ST[countST++].mCountSpanningEdges = countSpanningEdges;
}
/*Queue has five properties. capacity stands for the maximum number of elements
Queue can hold.
Size stands for the current size of the Queue and elements is the array of elements.
front is the
index of first element (the index at which we remove the element) and rear is the
index of last element
(the index at which we insert the element) */
typedef struct Queue
{
int capacity;
int size;
int front;
int rear;
int *elements;
}Queue;

9


/* createQueue function takes argument the maximum number of elements the
Queue can hold, creates
a Queue according to it and returns a pointer to the Queue. */
Queue * CreateQueue(int maxElements)
{

/* Create a Queue */
Queue *Q;
Q = (Queue *)malloc(sizeof(Queue));
/* Initialise its properties */
Q->elements = (int *)malloc(sizeof(int)*maxElements);
Q->size = 0;
Q->capacity = maxElements;
Q->front = 0;
Q->rear = -1;
/* Return the pointer */
return Q;
}
void Dequeue(Queue *Q)
{
/* If Queue size is zero then it is empty. So we cannot pop */
if(Q->size==0)
{
printf("Queue is Empty\n");
return;
}
/* Removing an element is equivalent to incrementing index of front by one */
else
{
Q->size--;
Q->front++;
/* As we fill elements in circular fashion */
if(Q->front==Q->capacity)
{
Q->front=0;
}

}
return;
}

10


void Enqueue(Queue *Q,int element)
{
/* If the Queue is full, we cannot push an element into it as there is no space for
it.*/
if(Q->size == Q->capacity)
{
printf("Queue is Full\n");
}
else
{
Q->size++;
Q->rear = Q->rear + 1;
/* As we fill the queue in circular fashion */
if(Q->rear == Q->capacity)
{
Q->rear = 0;
}
/* Insert the element in its rear side */
Q->elements[Q->rear] = element;
}
return;
}
bool CheckExist(int T[], int m, int n){

for(int i = 0; i < m; i++){
if(T[i] == n){
return true;
}
}
return false;
}
void ReadFromAFile(int a[][2], int &n, int &m){
FILE *f;
f=fopen("GRAPH.INP", "r");
fscanf(f, "%d", &n);
fscanf(f, "%d", &m);
for(int i = 0; i < m; i++){
for (int j = 0; j < 2; j ++ ){
fscanf(f, "%d", &a[i][j]);
}
}
fclose(f);
}
11


void WriteToAFile(SpanningTree ST[], int countST){
FILE *f;
f=fopen("GRAPH.OUT", "w+");
fprintf(f, "%d ", countST);
fprintf(f, "\n");
for(int i = 0; i< countST; i++){
for(int j = 0; j < ST[i].mCountT; j++){
if(j != ST[i].mCountT - 1){

fprintf(f, "%d, ", ST[i].mT[j]);
}else{
fprintf(f, "%d ", ST[i].mT[j]);
}
}
fprintf(f, "\n");
for(int j = 0; j < ST[i].mCountSpanningEdges; j++){
if(j != ST[i].mCountSpanningEdges - 1){
fprintf(f, "(%d, %d), ", ST[i]. mSpanningEdges[j][0], ST[i]. mSpanningEdges[j]
[1]);
}else{
fprintf(f, "(%d, %d) ", ST[i]. mSpanningEdges[j][0], ST[i]. mSpanningEdges[j][1]);
}
}
fprintf(f, "\n");
}
fclose(f);
}
void NewInputGraph(int a[][2], int &n, int &m, int T[], int countT, int a2[][2], int &n2, int
&m2){
n2 = n - countT;
int flag[m];
for(int j = 0; j < m; j++){
flag[j] = 0;
}
for(int i = 0; i < countT; i++){
for(int j = 0; j < m; j++){
if(a[j][0] == T[i] || a[j][1] == T[i]){
flag[j] = 1;
}

}
}
for(int j = 0; j < m; j++){
if(flag[j]==0){
a2[m2][0] = a[j][0];
a2[m2++][1] = a[j][1];
}
}
}
12


bool BFSSpanningTree(int a[][2], int n, int m, int T[], int &countT, int SpanningEdges[][2],
int &countSpanningEdges)
{
Queue *Q = CreateQueue(MAX);
Enqueue(Q, a[0][0]);
T[countT++] = a[0][0];
int currentEdge = 0;
int currentVertice;
int nextVertice;
while(Q->size > 0)
{
currentVertice = Front(Q);
printf("Dang duyet dinh %d\n", currentVertice);
Dequeue(Q);
for(int i = 0; i < m; i++){
for (int j = 0; j < 2; j ++ ){
if(a[i][j]==currentVertice){
if(j==0){

nextVertice=a[i][1];
}else{
nextVertice=a[i][0];
}
if(CheckExist(T, n, nextVertice)==false){
T[countT++]=nextVertice;
//printf("Dang duyet nextVertice %d\n",

nextVertice);

SpanningEdges[countSpanningEdges][0]=a[i][0];
SpanningEdges[countSpanningEdges++][1]=a[i]
[1];

Enqueue(Q, nextVertice);
}
}

}

}

}
if(countT == n){
return true;
}else{
return false;
}
}


13


int main()
{
printf("***********************************************\n");
printf("\n");
printf("TIM CAY PHU THEO CHIEU NGANG\n");
printf("Hoc vien: NGUYEN TRONG AN\n");
printf("Lop: K30 KHMT\n");
printf("\n");
printf("***********************************************\n");
printf("\n");
printf("\n");
int a[MAX][2];
int n, m;
int SpanningEdges[MAX][2];
printf("Doc file input GRAPH.INP...\n");
ReadFromAFile(a, n, m);
int T[MAX];
int countT = 0;
int countSpanningEdges = 0;
printf("So dinh: %d\n", n);
printf("So canh: %d\n", m);
printf("Dang xu ly...\n");
int countLT = 0;
SpanningTree ST[MAX];
int countST = 0;
bool result = BFSSpanningTree(a, n, m, T, countT, SpanningEdges,
countSpanningEdges);

if(result){
SpanningTreeToArray(ST, countST, T, countT, SpanningEdges,
countSpanningEdges);
}else{
SpanningTreeToArray(ST, countST, T, countT, SpanningEdges,
countSpanningEdges);
int a2[MAX][2];
int n2=0, m2=0;
NewInputGraph( a, n, m, T, countT, a2, n2, m2);
countT = 0;
countSpanningEdges = 0;
result = BFSSpanningTree(a2, n2, m2, T, countT, SpanningEdges,
countSpanningEdges);
while(result == false){
SpanningTreeToArray(ST, countST, T, countT, SpanningEdges,
countSpanningEdges);
14


NewInputGraph( a, n, m, T, countT, a2, n2, m2);
countT = 0;
countSpanningEdges = 0;
result = BFSSpanningTree(a2, n2, m2, T, countT, SpanningEdges,
countSpanningEdges);
}
SpanningTreeToArray(ST, countST, T, countT, SpanningEdges,
countSpanningEdges);
}
printf("So thanh phan lien thong: %d\n", countST);
if(countST == 1){

printf("Do thi co cay phu. Da ghi ket qua ra file GRAPH.OUT...\n");
}else{
printf("Do thi khong lien thong. Rung phu da duoc ghi ra file GRAPH.OUT...\n");
}
WriteToAFile(ST, countST);
printf("Ket thuc.\n");
getch();
return 0;
}

15


KẾT LUẬN
 Em đã nắm bắt được một phần lý thuyết cơ bản về đồ thị toán ứng dụng.
 Xây dựng được thuật toán tìm cây phủ theo chiều ngang
 Áp dụng thuật toán cho bài toán đồ thị không liên thông

16


TÀI LIỆU THAM KHẢO
[1] PGS.TSKH. Trần Quốc Chiến – Bài Giảng Toán Ứng Dụng – Trường Đại Học
Bách Khoa Đà Nẵng - 2015.
[2] Các tài liệu trên Internet.

17




×