Showing posts with label Thuật toán. Show all posts
Showing posts with label Thuật toán. Show all posts

Monday, January 11, 2010

Giải thuật Leo đồi


1. Kỹ thuật tìm kiếm leo đồi
Tìm kiếm leo đồi là tìm kiếm theo độ sâu được hướng dẫn bởi hàm đánh giá. Song khác với tìm kiếm theo độ sâu, khi phát triển một đỉnh u thì bước tiếp theo ta chọn trong số các đỉnh con của u, đỉnh có hứa hẹn nhiều nhất để phát triển, đỉnh này được xác định bởi hàm đánh giá.
2. Giải thuật
Input:
    Đồ thị G = (V,E), đỉnh xuất phát n0.
    Hàm đánh giá h(n) đối với mỗi đỉnh n.
    Tập đỉnh đích DICH
Output:
    Đường đi từ đỉnh n0 đến DICH


            bool result = false;
            openList.Push(n0);
            while (!openList.IsEmpty())
            {
                node = openList.Pop();
                if (node.Equals(n*))
                {
                    result = true;
                    break;
                }

                closeList.Push(node);
                Stack list = new Stack();
                for (n in Tn(node))
                {
                    if (!openList.InList(n) && !closeList.InList(n))
                    {
                        n.Cost = node.Cost + Edge(node, n).Value + n.Huerictis;
                        BeforeOfNode(n, node);
                        list.Push(n);
                    }
                }
                list.Sort(SortType.DESCENDING);//sắp xếp các đỉnh phát triển tiếp theo theo thứ tự hàm đánh giá
                while (!list.IsEmpty())
                {
                    openList.Push(list.Pop());//chuyển các đỉnh tiếp theo vào danh sách OPEN theo thứ tự hàm đánh giá
                }
            }
            if (result)
            {
                DisplayResult();
            }
            else
            {
                NotFound();
            }
3. Ví dụ
Cho đồ thị như hình vẽ

Với giá trị Hueristic của mỗi đỉnh như sau

H(1) = 1  H(2) = 3  H(3) = 5   H(4) = 6  H(5) = 4
H(6) = 1  H(7) = 2  H(8) = 3   H(9) = 1  H(10) = 6

Đỉnh xuất phát là (1), đỉnh đích là (10)

Các bước chi tiết thực hiện giải thuật


Kết quả 

Chi phí 24




Mã nguồn tham khảo tại đây 


Giải thuật A* - Tìm kiếm cực tiểu


1. Tìm kiếm cực tiểu sử dụng hàm đánh giá - Thuật toán A*

Đối với nhiều bài toán, việc tìm kiếm đường đi cực tiểu sẽ được định hướng tập trung xung quanh  đường đi tốt nhất; nếu sử dụng các thông tin đặc tả về bài toán gọi là các heuristic.
Đối với việc tìm kiếm đường đi với chi phí cực tiểu, người ta sử dụng hàm đánh giá heuristic như sau:
    Gọi g(n): giá cực tiểu đường đi từ n0->n. Tại đỉnh n, g(n) xác định được.
    Gọi h(n): giá cực tiểu đường đi từ n->DICH, h(n) không xác định được Þ người ta tìm cách ước lượng giá trị này.
    Đặt f0(n)=g0(n)+h0(n): dự đoán chi phí cực tiểu của đường đi từ n0->DICH có đi qua đỉnh n.
    g0(n) là chi phí của đường đi từ đỉnh xuất phát đến đỉnh n tại thời điểm đang xét. h0(n) là ước lưọng (dự đoán) chi phí đường đi từ đỉnh n đến đích. Việc chọn giá trị xấp xỉ h0(n) của h(n) không có một phương pháp tổng quát và được xem như một nghệ thuật. Giá trị này sẽ do các chuyên gia đưa ra.
Lúc này giải thuật tìm kiếm cực tiểu sẽ thay việc xét hàm g bởi hàm f.
2. Giải thuật

Input:
    Đồ thị G = (V,E), Đỉnh xuất phát n0
    Hàm chi phí c: c(i,j): xác định chi phí chuyển từ đỉnh i sang đỉnh j
    h: h(n) xác định dự đoán chi phí tối ưu của đường đi từ đỉnh n đến đích.

Tập các đỉnh đích DICH
Output:
Đường đi từ đỉnh n0 đến đỉnh n* thuộc DICH với giá thành cực tiểu



            bool result = false;
            openList.Push(n0);
            while (!openList.IsEmpty())
            {
                node = openList.Pop();
                if (node.Equals(n*))
                {
                    result = true;
                    break;
                }

                closeList.Push(node);
                for (n in Tn(node))
                {
                    if (!openList.InList(n) && !closeList.InList(n))
                    {
                        openList.Push(n);
                        n.Cost = node.Cost + Edge(node, n).Value + n.Huerictis;
                        BeforeOfNode(n, node);
                    }
                    else if (!closeList.InList(n) && n.Cost > node.Cost + Edge(node, n).Value + n.Huerictis)
                    {
                        n.Cost = node.Cost + Edge(node, n).Value + n.Huerictis;
                        BeforeOfNode(n, node);
                    }
                }
                openList.Sort(SortType.ASCENDING);//sắp xếp theo chi phí của mỗi đỉnh, giá trị Min ở đỉnh Stack
            }

            if (result)
            {
                DisplayResult();
            }
            else
            {
                NotFound();
            }

3. Ví dụ

Cho đồ thị như hình vẽ

Với giá trị Hueristic của mỗi đỉnh như sau

H(1) = 1  H(2) = 3  H(3) = 5   H(4) = 6  H(5) = 4
H(6) = 1  H(7) = 2  H(8) = 3   H(9) = 1  H(10) = 6

Đỉnh xuất phát là (1), đỉnh đích là (10)

Các bước chi tiết thực hiện giải thuật


Kết quả

Với chi phí cực tiểu là 18


Mã nguồn tham khảo tại đây 
 

Sunday, January 10, 2010

Giải thuật AT - giá thành cực tiểu


1. Tìm kiếm đường đi có giá thành cực tiểu - Thuật toán AT
Cho đồ thị G= (V, E) biểu diễn bài toán với đỉnh xuất phát n0 và tập đích DICH xác định.
Với mỗi phép chuyển trạng thái n(i)->n(i+1) tốn chi phí c(i, i+1), ở đây có thể xem là trọng số của cung nối n(i) và n(i+1)
Phương pháp
Tương tự phương pháp tìm kiếm theo chiều sâu, nhưng tại mỗi biết ta tính giá thành của mỗi đỉnh và chọn đỉnh có giá thành tối ưu nhất
2. Giải thuật
Input:
    Đồ thị G = (V,E), Đỉnh xuất phát n0
    Hàm chi phí c
    Tập các đỉnh đích DICH
Output:
Đường đi từ đỉnh n0 đến đỉnh n* in DICH sao cho g(n*) = MIN


            bool result = false;
            openList.Push(n0);
            while (!openList.IsEmpty())
            {
                node = openList.Pop();
                if (node.Equals(n*))
                {
                    result = true;
                    break;
                }
                closeList.Push(node);
                for (n in Tn(node))
                {
                    if (!openList.InList(n) && !closeList.InList(n))
                    {
                        openList.Push(n);
                        n.Cost = node.Cost + Edge(node, n).Value;
                        BeforeOfNode(n, node);
                    }
                    else if (!closeList.InList(n) && n.Cost > node.Cost + Edge(node, n).Value)
                    {
                        n.Cost = node.Cost + Edge(node, n).Value;
                        BeforeOfNode(n, node);
                    }
                }
                openList.Sort(SortType.ASCENDING);//sắp xếp lại để chọn đỉnh tối ưu nhất ở đỉnh Stack
            }

            if (result)
            {
                DisplayResult();
            }
            else
            {
               NotFound();
            }

3. Ví dụ
Cho đồ thị như hình vẽ

Đỉnh xuất phát là (1), đỉnh đích là (10)

Các bước chi tiết thực hiện giải thuật

 
Kết quả
 
Chi phí là 6


Mã nguồn tham khảo tại đây 
 

Giải thuật tìm kiếm tốt nhất đầu tiên



1. Kỹ thuật tìm kiếm tốt nhất đầu tiên
Kỹ thuật tìm kiếm tốt nhất đầu tiên tìm lời giải có dùng tri thức về bài toán để hướng dẫn. Tri thức này hướng việc tìm kiếm về nút lời giải trong không gian bài toán.
Tại mỗi nút được xem xét, người ta sẽ quyết định việc tìm kiếm tiếp tục theo nhánh nào tin tưởng sẽ dẫn đến lời giải.
Trong các chương trình trí tuệ nhân tạo, kỹ thuật tìm kiếm tốt nhất đầu tiên sử dụng hàm đánh giá. Hàm này dùng các thông tin hiện tại về mức độ quan trọng của bài toán tại nút đó để gán giá trị cho nút này, gọi là trọng số của nút. Giá trị này được xem xét trong lúc tìm kiếm. Thông thường, nút có trọng số nhỏ (lớn) nhất sẽ được chọn trong quá trình tìm kiếm.    
2. Hàm đánh giá               
Trong nhiều vấn đề, ta có thể sử dụng kinh nghiệm, tri thức của chúng ta về vấn đề đó để đánh giá các trạng thái của vấn đề.
Với mỗi trạng thái u, ta sẽ xác dịnh một giá trị số h(u), số này đánh giá “sự gần đích” của trạng thái u. Hàm h(u) được gọi là hàm đánh giá.
Phương pháp tìm kiếm kinh nghiệm là phương pháp tìm kiếm có sử dụng đến hàm đánh giá. Trong quá trình tìm kiếm, tại mỗi bước ta sẽ chọn trạng thái kế tiếp là trạng thái có nhiều hứa hẹn dẫn tới đích nhiều nhất.
Quá trình tìm kiếm trong không gian trạng thái có sử dụng hàm đánh giá bao gồm các bước cơ bản sau:
Biểu diễn thích hợp các trạng thái và các toán tử chuyển trạng thái
Xây dựng hàm đánh giá
Thiết kế chiến lược chọn trạng thái ở mỗi bước


3. Giải thuật

            bool result = false;
            openList.Push(n0);
            while (!openList.IsEmpty())
            {
                node = openList.Pop();
                if (node.Equals(n*))
                {
                    result = true;
                    break;
                }

                closeList.Push(node);
                for (n in Tn(Node))
                {
                    if (!openList.InList(n) && !closeList.InList(n))
                    {
                        n.Cost = n.Huerictis;
                        openList.Push(n);
                        BeforeOfNode(n, node);
                    }
                }
                openList.Sort(SortType.ASCENDING);//sắp xếp theo thứ tự giảm dần theo Cost từ đỉnh Stack
            }

            if (result)
            {
                DisplayResult();
            }
            else
            {
                NotFound();
            }
4. Ví dụ
Cho đồ thị như hình vẽ


Với giá trị Hueristic của mỗi đỉnh như sau

H(1) = 1  H(2) = 3  H(3) = 5   H(4) = 6  H(5) = 4
H(6) = 1  H(7) = 2  H(8) = 3   H(9) = 1  H(10) = 6

Đỉnh xuất phát là (1), đỉnh đích là (10)

Các bước chi tiết thực hiện giải thuật

Kết quả
 
 
 5. Ưu và nhược điểm của phương pháp tìm kiếm tốt nhất đầu tiên
Ưu điểm
- Phương pháp tìm kiếm tốt nhất đầu tiên tổ hợp các ưu điểm của phương pháp tìm kiếm rộng và tìm kiếm sâu.
- Ưu điểm chủ yếu của phương pháp tìm kiếm tốt nhất đầu tiên là dùng tri thức để dẫn dắt việc tìm kiếm. Tri thức này giúp người ta bắt đầu từ đâu là tốt nhất và cách tốt nhất để tiến hành tìm lời giải.
- Tìm kiếm tốt nhất đầu tiên tuân theo cách suy lý của một chuyên gia. Do đó có thể thấy rõ đường đi hơn tìm kiếm rộng và tìm kiếm sâu.
Nhược điểm
- Quá trình tìm kiếm có thể đi xa khỏi lời giải. Kỹ thuật này chỉ xét một phần của không gian và coi đó là phần hứa hẹn hơn cả.


Mã nguồn tham khảo tại đây

Giải thuật tìm kiếm sâu dần


1. Kỹ thuật tìm kiếm sâu dần
Kỹ thuật tìm kiếm sâu dần là thực hiện việc tìm kiếm với độ sâu ở mức giưói hạn d nào đó. Nếu không tìm ra nghiệm ta tăng độ sâu lên d+1 và lại tìm kiếm theo độ sâu tới mức d+1. Quá trình trên được lặp lại với d lần lượt là 1, 2,...đến độ sâu max nào đó. 
Kỹ thuật tìm kiếm sâu dần thường được thực hiện khi cây tìm kiếm chứa nhánh vô hạn, và nếu sử dụng tìm kiếm theo độ sâu ta có thể mắc kẹt ở một nhánh nào đó (thuật toán không dừng) và không tìm ra nghiệm
2. Giải thuật
Thuật toán tìm kiếm sâu dần sử dụng thuật toán tìm kiếm sâu hạn chế như thủ tục con. Đó là thủ tục tìm kiếm theo chiều sâu nhưng chỉ tới độ sâu d nào đó rồi quay lên.


            bool result = false;
            openList.Push(n0);
            deepOfNode(no, 0);//độ sâu của đỉnh xuất phát là 0
            while (!openList.IsEmpty())
            {
                node = openList.Pop();
                if (node.Equals(n*))
                {
                    result = true;
                    break;
                }

                closeList.Push(node);
                int deep = deepOfNode[node];
                if (deep < limitedDeep)
                {
                    for (n in Tn(node))
                    {
                        if (!openList.InList(n) && !closeList.InList(n))
                        {
                            openList.Push(n);
                            BeforeOfNode(n, node);
                            deepOfNode.Add(n, deep + 1);//độ sâu của đỉnh n
                        }
                    }
                }
            }

            if (result)
            {
                DisplayResult();
            }
            else
            {
                NotFound();
            }

3. Ví dụ

Cho đồ thị như hình vẽ

Đỉnh xuất phát là (1), đỉnh đích là (11), độ sâu giới hạn là 3

Các bước chi tiết thực hiện giải thuật


Kết quả



Mã nguồn tham khảo tại đây 
 

Giải thuật tìm kiếm theo chiều sâu


1. Kỹ thuật tìm kiếm sâu 
Tìm kiếm sâu trong không gian bài toán được bắt đầu từ một nút rồi tiếp tục cho đến khi hoặc đến ngõ cụt hoặc đến đích. Tại mỗi nút có luật trong tài, chẳng hạn, “đi theo nút cực trái”, hướng dẫn việc tìm. Nếu không đi tiếp được, gọi là đến ngõ cụt, hệ thống quay lại một mức trên đồ thị và tìm theo hướng khác, chẳng hạn, đến nút “sát nút cực trái”. Hành động này gọi là quay lui.
Thuật toán tìm kiếm theo chiều sâu được hình dung như việc khảo sát một cây bắt đầu từ gốc đi theo mọi cành có thể được, khi gặp cành cụt thì quay lại xét cành chưa đi qua.
- Ở bước tổng quát, giả sử đang xét đỉnh i, khi đó các đỉnh kề với i có các trường hợp:
  + Nếu tồn tại đỉnh j kề i chưa được xét thì xét đỉnh này (nó trở thành đỉnh đã xét) và bắt đầu từ đó tiếp tục quá trình tìm kiếm với đỉnh này..
  + Nếu với mọi đỉnh kề với i đều đã được xét thì i coi như duyệt xong và quay trở lại tìm kiếm từ đỉnh mà từ đó ta đi đến được i.

2. Giải thuật
Input:
Cây/Đồ thị G = (V,E) với đỉnh gốc là n0 (trạng thái đầu)
    Tập đích Goals
Output:
Một đường đi p từ n0 đến một đỉnh n* in Goals
Method:
Sử dụng hai danh sách hoạt động theo nguyên tắc LIFO (Stack)  OPENLIST và CLOSELIST


            openList.Push(n0);
            while (!openList.IsEmpty())
            {
                node = openList.Pop();
                if (node.Equals(n*))
                {
                    result = true;
                    break;
                }

                closeList.Push(node);
                for (n in Tn(Node))
                {
                    if (!openList.InList(n) && !closeList.InList(n))
                    {
                        openList.Push(n);
                BeforeOfNode(n, node);////node trước của n là node trong quá trình tìm đường đến đích
                    }
                }
            }

            if (result)
            {
                DisplayResult();
            }
            else
            {
                NotFound();
            }
3. Ví dụ

Cho đồ thị như hình vẽ

Đỉnh xuất phát là (1), đỉnh đích là (11)

Các bước chi tiết thực hiện giải thuật

 

 Kết quả đường đi là:


4. Ưu và nhược điểm của phương pháp tìm kiếm sâu
Ưu điểm:
- Nếu bài toán có lời giải, phương pháp tìm kiếm sâu bảo đảm tìm ra lời giải.
- Kỹ thuật tìm kiếm sâu tập trung vào đích, con người cảm thấy hài lòng khi các câu hỏi tập trung vào vấn đề chính.
- Do cách tìm của kỹ thuật này, nếu lời giải ở rất sâu, kỹ thuật tìm sâu sẽ tiết kiệm thời gian.
Nhược điểm:
- Tìm sâu khai thác không gian bài toán để tìm lời giải theo thuật toán đơn giản một cách cứng nhắc. Trong quá trình tìm nó không có thông tin nào hổ trợ để phát hiện lời giải. Nếu chọn nút ban đầu không thích hợp có thể không dẫn đến đích của bài toán.
- Không phù hợp với không gian bài toán lớn, kỹ thuật tìm kiếm sâu có thể không đến lời giải trong khoảng thời gian vừa phải.


Mã nguồn tham khảo tại đây 

Giải thuật tìm kiếm theo chiều rộng

1. Kỹ thuật tìm kiếm rộng
Kỹ thuật tìm kiếm rông là tìm kiếm trên tất cả các nút của một mức trong không gian bài toán trước khi chuyển sang các nút của mức tiếp theo.
Kỹ thuật tìm kiếm rộng bắt đầu từ mức thứ nhất của không gian bài toán, theo hướng dẫn của luật trọng tài, chẳng hạn “đi từ trái sang phải”. Nếu không thấy lời giải tại mức này, nó chuyển xuống mức sau để tiếp tục … đến khi định vị được lời giải nếu có.
 

2. Giải thuật
Input:
Cây/Đồ thị G = (V,E) với đỉnh gốc là n0 (trạng thái đầu)
    Tập đích Goals
Output:
Một đường đi p từ n0 đến một đỉnh n* in Goals
Method:
Để thực hiện giải thuật này ta sử dụng hai danh sách hoạt động theo nguyên tắc FIFO (queue)  OPENLIST và CLOSELIST



            bool result = false;

            openList.Append(n0);


            while (!openList.IsEmpty())
            {
                node = openList.Take();

                if (node.Equals(n*))//là node đích
                {
                    result = true;
                    break;
                }

                closeList.Append(node);
                for (n in Tn(Node))
                {
                    if (!openList.InList(n) && !closeList.InList(n))
                    {
                        openList.Append(n);
                        BeforeOfNode(n, node);//node trước của n là node trong quá trình tìm đường đến đích
                    }
                }
            }

            if (result)
            {
                DisplayResult();
            }
            else
            {
                NotFound();
            }
        }
 

3. Ví dụ


Cho đồ thị như hình vẽ

Đỉnh xuất phát là (1), đỉnh đích là (11)

Các bước chi tiết thực hiện giải thuật


 

Kết quả đường đi là: 


4. Ưu và nhược điểm của phương pháp tìm kiếm rộng
Ưu điểm
- Kỹ thuật tìm kiếm rộng là kỹ thuật vét cạn không gian trạng thái bài toán vì vậy sẽ tìm được lời giải nếu có.
- Đường đi tìm được đi qua ít đỉnh nhất.

Nhược điểm
- Tìm kiếm lời giải theo thuật toán đã định trước, do vậy tìm kiếm một cách máy móc; khi không có thông tin hổ trợ cho quá trình tìm kiếm, không nhận ra ngay lời giải.
- Không phù hợp với không gian bài oán kích thước lớn. Đối với loại bài toán này, phương pháp tìm rộng đối mặt với các nhu cầu:
  + Cần nhiều bộ nhớ theo số nút cần lưu trữ.
  + Cần nhiều công sức xử lý các nút, nhất là khi các nhánh cây dài, số nút tăng. 

  + Dễ thực hiện các thao tác không thích hợp, thừa, đưa đến việc tăng đáng kể số nút phải xử lý.
- Không hiệu qủa nếu lời giải ở sâu. Phương pháp này không phù hợp cho trường hợp có nhiều đường dẫn đến kết quả nhưng đều sâu.
- Giao tiếp với người dùng không thân thiện. Do duyệt qua tất cả các nút, việc tìm kiếm không tập trung vào một chủ đề. 


Mã nguồn tham khảo tại đây

Saturday, October 27, 2007

Thuật toán sắp xếp: Quick Sort (P.2)

Thuật toán Quick Sort
o Ý tưởng
Ta chọn một phần tử bất kỳ của mảng A giả sử đó là x
Lọc và chia mảng đó thành 3 mảng con:
- mảng A1: A1(i) <>
- mảng A2: A2(i) = x với mọi i
- mảng A3: A3(i) > x với mọi i
Sau đó ta lại tiếp tục các bước trên với mảng A1 và A3. Công việc này còn được gọi là phân hoạch nên Quick Sort còn được gọi là sắp xếp theo phương pháp phân hoạch
Giải thuật này sẽ được cài đặt theo phương pháp đệ qui

o Mô tả thuật toán
- Input: Mảng A[1..n]
- Output: Mảng A có thứ tự tăng dần
- Method:

function quickSort(A, lower, upper){
x = A[(lower + upper) / 2];
i = lower;
j = upper;
do{
while(A[i] <>
i ++;
while (A[j] > x)
j --;
if (i <= j){
swap(A[i], A[j]);
i ++;
j --;
}
}while(i <= j);
if (j > lower)
quickSort(A, lower, j);
if (i <>
quickSort(A, i, upper);
}


o Độ phức tạp tính toán: O(nlnn)

Thuật toán Quick Sort tốt nhất trong trường hợp dãy hầu như được sắp xếp và với n khá lớn. Vì vậy ta thường dung Quick Sort trong giai đoạn đầu để phân hoạch, khi đoạn con đủ nhỏ ta sẽ dùng các phương pháp khác để sắp xếp

Friday, October 26, 2007

Sắp xếp mảng (P.1)

Sắp xếp mảng số nguyên một chiều A theo thứ tự tăng dần (hoặc giảm dần)


1.Thuật toán sắp xếp kiểu chọn lựa
o Ý tưởng
Giả sử ta đã sắp xếp mảng cho đến phần tử thứ i – 1 theo thứ tự tăng dần.
Ở bước thứ i ta chọn phần tử có giá trị nhỏ nhất trong đoạn A[i..n], giả sử A(j), ta thực hiện đổi chỗ A(i) với A(j)

o Mô tả thuật toán
- Input: Mảng A[1..n]
- Output: Mảng A có thứ tự tăng dần
- Method:

function sort(A){
for(i = 1; i <>
j = i;
for(k = i + 1; k <= n; k ++)
if (A[k] <>
j = k;
swap(A[i], A[j]);
}
}



o Độ phức tạp tính toán: O(n2)

2. Thuật toán sắp xếp kiểu chèn
o Ý tưởng
Giả sử ta đã sắp xếp mảng cho đến phần tử thứ i -1 theo thứ tự tăng dần.
Ở bước thứ i sẽ thực hiện chèn giá trị A(i) vào dãy con A[1..i] sao cho dãy vẫn giữa được trật tự sắp xếp cũ (ý tưởng như vậy ta xếp các quân bài Tú – lơ – khơ từ 1 đến K)
Ta thực hiện như sau: Xuất phát từ j = i -1 xét trở về phía trước
- nếu A(j) <= x = A(i): ta đặt x vào vị trí j + 1
- nếu A(j) > x: ta gán A(j) vào cho A(j + 1), sau đó quay về phía trước 1 phần tử và tiếp tục lại quá trình này
Để bài toán thực hiện được theo ý tưởng này thì ở đầu mảng phải có 1 phần tử làm mốc A(0) không phải thuộc mảng gốc, nó chỉ đóng vai trò là giá trị ‘vô cực’ mà thôi

o Mô tả thuật toán
- Input: Mảng A[1..n]
- Output: Mảng A có thứ tự tăng dần
- Method:

function sort(A){
A[0] = VO_CUNG;
for(i = 2; i <= n; i++){
x = A[i];
j = i – 1;
while(x <>
A[j + 1] = A[j];
j --;
}
A[j] = x;
}
}


o Độ phức tạp tính toán: O(n2)

3. Thuật toán sắp xếp kiểu nổi bột hay đổi chỗ
o Ý tưởng
Giả sử ta đã sắp xếp được mảng đến phần tử i – 1
Tại bước i, ta sẽ duyệt đoạn A[i..n] từ n trở về i, nếu A(j – 1) > A(j) thì đổi chỗ, sau khi duyệt xong đoạn A[i..n] thì đoạn từ 1 đến i được sắp xếp

o Mô tả thuật toán
- Input: Mảng A[1..n]
- Output: Mảng A có thứ tự tăng dần
- Method:

function sort(A){
for(i = 2; i <= n; i++)
for(j = n; j > i; j--)
if (A[j] <>
swap(A[j], A[j - 1]);
}



Ta cũng có thể cải tiến một chút giải thuật trên, mặc dù độ phức tạp tình toán vẫn vậy. Đến khi nào không thấy có việc đổi chỗ nữa (đoạn sau đã có thứ tự sắp xếp thỏa mãn thì ta dừng luôn)

function sort(A){
i = 2;
do{
flag = true;
for (j = n; j > i; j--)
if (A[j] <>
swap(A[j], A[j - 1]);
flag = false;
}

i ++;
}while (flag = true);
}


o Độ phức tạp tính toán: O(n2)

Tìm kiếm trên mảng

1. Thuật toán tìm kiếm nhị phân
o Bài toán
Cho một mảng các số được sắp xếp tăng dần (giảm dần), cho một giá trị x, xác định xem x có thuộc mảng đó hay không

o Ý tưởng
Giả sử mảng sắp xếp tăng dần A, ta chia đôi mảng, so sánh x với phần tử ở giữa A[mid], nếu:
- x == A[mid] : return true
- x > A[mid]: tiếp tục tìm x trong nửa mảng bên phải
- x < A[mid]: tiếp tục tìm x trong nửa mảng bên trái

o Mô tả thuật toán
- Input: mảng A[1..n] giá trí x
- Output:
+ x thuộc A: true
+ else false
- Method :
function binarySearch(A, x, first, last){
if (first > last)

return false;
else{
mid = (first + last) / 2;
if (x == A[mid])
return true;
else if (x < A[mid])
return binarySearch (A, x, first, mid - 1);
else
return binarySearch (A, x, mid + 1, last);
}
}

o Độ phức tạp tính toán: O(lgn)

2. Thuật toán tìm Min Max
o Bài toán
Tìm giá trí Min và Max trong đoạn [left, right] của mảng A[1,n]

o Ý tưởng
Chia mảng đoạn [left, right] thành 2 phần, tìm Min và Max trong 2 phần đó sau đó so sánh 2 kết quả này với nhau. Tiếp tục việc chia 2 cho đến khi đoạn chia chỉ còn 1 phần tử thì Min = Max và bằng phần tử đó

o Mô tả thuật toán
- Input: Mảng A[1..n]
Left và Right
- Output:
Min và Max của đoạn [Left, Right]
- Method:

function minMax(A, left, right, Min, Max){
if (left == right)
Min = Max = A[left];
else{
minMax(A, left, (right + left) / 2, Min1, Max1);
minMax(A, (right + left) / 2 + 1, right, Min2, Max2);
if (Min1 > Min2)
Min = Min2;
else
Min = Min1;
if(Max1 > Max2)
Max = Max1;
else
Max = Max2;
}
}

o Độ phức tạp tính toán: O(n)