Các giải thuật tìm kiếm cơ bản

Một phần của tài liệu Baigiang dung chung kythuatlaptrinh (Trang 125 - 134)

Hai giải thuật tìm kiếm cơ bản là tìm kiếm tuần tự và tìm kiếm nhị phân. Ngoài ra, chúng ta tìm hiểu và cài đặt phương pháp tìm kiếm dựa trên một cấu trúc dữ liệu đặc biệt là Cây nhị phân tìm kiếm (xem lại chương 4- Cây).

7.2.1. Tìm kiếm tuần tự

Tìm kiếm tuần tự là phương pháp tìm kiếm đơn giản trên một danh sách chưa được sắp xếp. Phương pháp này duyệt từ bản ghi đầu tiên tới bản ghi cuối cùng và so sánh lần lượt giá trị của khóa với giá trị X cần tìm. Trong quá trình tìm kiếm, nếu tìm thấy bản ghi có khóa trùng với giá trị X thì đưa ra vị trí của bản ghi trong dãy, ngược lại nếu tìm đến cuối dãy mà không tìm thấy bản ghi nào có khóa trùng với X thì trả về giá trị -1 (tương ứng với không tìm thấy bản ghi).

Chương trình minh họa giải thuật tìm kiếm tuần tự #include <cstdlib>

#include <iostream> #include <stdlib.h> #include <conio.h> using namespace std;

void init(int *A,int n) {

cout<<"Tao lap day so "<<endl; for(int i=0;i<n;i++) { A[i]=rand()%1000; cout<<A[i]<<endl; } }

int tim_kiem(int *A,int n, int k) {

for(int i=0;i<=n;i++) {

if(A[i]==k) return (i); }

return (-1); }

int main(int argc, char *argv[]) {

int *A,n,k;

cout<<"Nhap vao so luong phan tu cua day" <<endl; cin>>n;

A=new int[n]; init(A,n);

cin>>k;

int vitri=tim_kiem(A,n,k);

if(k!=-1)cout<<"Gia tri can tim la: "<<k<<" o vi tri "<<vitri<<endl; else

cout<<"Khong tim thay gia tri can tim"<<endl; system("PAUSE");

return EXIT_SUCCESS; }

7.2.2. Tìm kiếm nhị phân

Tìm kiếm nhị phân là một phương pháp tìm kiếm phổ biến và có hiệu lực cao với một danh sách đã được sắp xếp.

Nội dung của phương pháp tìm kiếm này như sau:

So sánh khóa X với khóa của phần tử ở vị trí giữa danh sách. Gọi phần tử ở giữa là mid=(low+high)/2. Với low=0 và high=n-1.

Vì dãy đã được sắp xếp nên nếu X lớn hơn khóa của phần tử ở giữa thì phần tử cần tìm thuộc khoảng (mid+1,high), ngược lại nếu X nhỏ hơn khóa của phần tử ở giữa thì phần tử cần tìm thuộc khoảng (0,mid-1); nếu X bằng khóa của phần tử ở giữa thì mid là chỉ số của phần tử cần tìm. Ở bước tiếp theo, nếu X lớn hơn khóa của phần tử ở giữa thì dịch chuyển cận trên về vị trí mid-1, ngược lại dịch chuyển cận dưới về mid+1. Cứ lặp lại quá trình như vậy cho tới khi gặp khóa có nội dung trùng với X hoặc cần dưới vượt quá cận trên hay không tìm thấy phần tử X nào trong dãy.

Mô tả thuật toán tìm kiếm nhị phân như sau: int binary_search(int *A, int X,int n)

{

int mid,low=0,high=n-1; while(low<=high) {

mid=(low+high)/2;

if(X>A[mid]) low=mid+1; else if(X<A[mid])) high=mid-1; else return (mid);

}

return (-1)//X không thuộc dãy }

Chương trình minh họa giải thuật tìm kiếm nhị phân: #include<iostream>

using namespace std;

#define MAX 100 #include<time.h>

void Mangtang(int a[], int n); void Xuatmang(int a[], int n);

int Timkiemnhiphan(int a[], int n, int x);

void Mangtang(int a[], int n) {

a[0]=rand()%11;

srand((unsigned int )time(NULL)); for(int i=1;i<n;i++){

a[i]=a[i-1] + rand()%11+1; }

}

void Xuatmang(int a[], int n) {

for(int i=1;i<n;i++){ cout<<a[i]<<" "; }

}

int Timkiemnhiphan(int a[], int n, int x) {

int First=1, Last=n; while(First <=Last) {

int Mid=(First + Last)/2; if(x==a[Mid]) return Mid; if(x<a[Mid]) Last=Mid-1; else First=Mid+1; } return -1; } int main() { int n,*a,kq,x;

cout<<"Nhap n: "; cin>>n;

a=new int[n];//Cap phat bo nho dong cho mang Mangtang(a,n);

cout<<"Mang la : "; Xuatmang(a,n); cout<<endl;

cout<<"Nhap x can tim: "< cin>>x;

kq=Timkiemnhiphan(a,n,x); if(kq==-1)

cout<<"Khong tim thay so can tim trong day so "<<endl; else

cout<<"Gia tri can tim la: "<<x<<" la phan tu thu: "<<kq; cout<<endl; delete [] a;//Giải phóng bộ nhớ a= NULL; system("pause"); return(0); }

7.3. Cài đặt minh họa

Ngoài các cài đặt cơ bản về tìm kiếm tuần tự và tìm kiếm nhị phân sử dụng mảng như đã trình bày ở trên, phần này minh họa thêm chương trình cài đặt tìm kiếm nhị phân bằng đệ qui.

Giải thuật tìm kiếm nhị phân cài đặt sử dụng đệ qui: #include <cstdlib>

#include <iostream>

using namespace std; void init( int *a,int n) { a[0]=rand()%11; for(int i=0;i<n;i++) { a[i]=rand()%11+a[i-1]+1; } }

void xuatmang(int *a,int n) { for(int i=0;i<n;i++) { cout<<a[i]<<endl; } }

int tim(int *a,int left,int right,int x) {

int m;

if(left>right) return 0; m=(left+right)/2; if(a[m]==x) return m;

if(x<a[m]) return tim(a,left,m-1,x); return tim(a,m+1,right,x);

}

int main(int argc, char *argv[]) {

int *a,n,x;

cout<<"Nhap vao so phan tu cua mang"<<endl; cin>>n;

a=new int[n]; init(a,n);

xuatmang(a,n);

cout<<"Nhap vao phan tu can tim: "<<endl; cin>>x;

int z=tim(a,0,n,x); if(z!=0)

{cout<<"Phan tu can tim tai vi tri: "<<z<<endl; }

else cout<<"Khong tim thay phan tu trong day"<<endl; delete [] a;

a=NULL;

system("PAUSE"); return EXIT_SUCCESS; }

TÀI LIỆU THAM KHẢO

[1] Đỗ Xuân Lôi. Cấu trúc dữ liệu và giải thuật. NXB Đại học Quốc Gia Hà Nội, 2006. [2] Lê Minh Hoàng. Giải thuật và lập trình. Đại Học Sư phạm Hà Nội, 2002.

[3] Phạm Văn Ất. Kỹ thuật lập trình C cơ sở và nâng cao. NXB Giao Thông Vận Tải. [4] Mark Allen Weiss. Data Structures and Algorithms Analysis in C++ (Fourth edition). [5] Lê Hữu Lập – Nguyễn Duy Phương. Giáo trình kỹ thuật lập trình. NXB Bưu Điện, 2002.

Một phần của tài liệu Baigiang dung chung kythuatlaptrinh (Trang 125 - 134)

Tải bản đầy đủ (PDF)

(134 trang)