- Tổng quan
- Thuật toán chung
- Mã giả
- Minh họa
- Ví dụ C++
- Java Example
- Complexity Analysis Of The Insertion Sort Algorithm
- Conclusion
Cái nhìn sâu sắc về sắp xếp chèn với các ví dụ cổ điển.
Sắp xếp chèn là một kỹ thuật sắp xếp có thể được xem theo cách chúng ta chơi bài trên tay. Cách chúng ta chèn hoặc loại bỏ bất kỳ thẻ nào trong bộ bài, sắp xếp chèn hoạt động theo cách tương tự.
Kỹ thuật thuật toán sắp xếp chèn hiệu quả hơn so với kỹ thuật Sắp xếp bong bóng và Sắp xếp lựa chọn nhưng kém hiệu quả hơn so với các kỹ thuật khác như Quicksort và Merge sort.
Tổng quan
Trong kỹ thuật sắp xếp chèn, chúng ta bắt đầu từ phần tử thứ hai và so sánh nó với phần tử thứ nhất rồi đặt ở một nơi thích hợp. Sau đó, chúng tôi thực hiện quy trình này cho các phần tử tiếp theo.
Chúng tôi so sánh từng phần tử với tất cả các phần tử trước đó của nó và đặt hoặc chèn phần tử vào đúng vị trí của nó. Kỹ thuật sắp xếp chèn khả thi hơn đối với các mảng có số lượng phần tử nhỏ hơn. Nó cũng hữu ích để sắp xếp các danh sách được liên kết.
Danh sách được liên kết có một con trỏ tới phần tử tiếp theo (trong trường hợp danh sách được liên kết đơn) và cả một con trỏ tới phần tử trước đó (trong trường hợp danh sách được liên kết kép ). Do đó, việc triển khai sắp xếp chèn cho danh sách được liên kết trở nên dễ dàng hơn.
Hãy cùng khám phá tất cả về sắp xếp chèn trong hướng dẫn này.
Thuật toán chung
Bước 1 : Lặp lại các bước từ 2 đến 5 cho K = 1 đến N-1
Bước 2 : đặt nhiệt độ = A[K]
Bước 3 : đặt J = K– 1
Bước 4 : Lặp lại trong khi temp =A[J]
đặt A[J + 1] = A[J]
đặt J = J – 1
[kết thúc vòng lặp bên trong]
Bước 5 : đặt A[J + 1] = temp
[ kết thúc vòng lặp]
Bước 6 : thoát
Như vậy, trong kỹ thuật sắp xếp chèn, chúng ta bắt đầu từ phần tử thứ hai vì chúng ta giả sử rằng phần tử đầu tiên luôn được sắp xếp . Sau đó, từ phần tử thứ hai đến phần tử cuối cùng, chúng ta so sánh từng phần tử với tất cả các phần tử trước đó của nó và đặt phần tử đó vào vị trí thích hợp.
Mã giả
Mã giả cho sắp xếp chèn được đưa ra dưới đây.
procedure insertionSort(array,N ) array – array to be sorted N- number of elements begin int freePosition int insert_val for i = 1 to N -1 do: insert_val = array[i] freePosition = i //locate free position to insert the element whilefreePosition> 0 and array[freePosition -1] >insert_val do: array [freePosition] = array [freePosition -1] freePosition = freePosition -1 end while //insert the number at free position array [freePosition] = insert_val end for end procedure
Ở trên là mã giả cho sắp xếp chèn, tiếp theo, chúng tôi sẽ minh họa kỹ thuật này trong ví dụ sau.
Minh họa
Mảng được sắp xếp như sau:
Bây giờ với mỗi lần vượt qua, chúng ta so sánh phần tử hiện tại với tất cả các phần tử trước đó của nó. Vì vậy, trong lượt đầu tiên, chúng tôi bắt đầu với phần tử thứ hai.
Vì vậy, chúng tôi cần N số lượt để sắp xếp hoàn toàn một mảng chứa N phần tử.
Hình minh họa trên có thể được tóm tắt dưới dạng bảng:
Đạt | Danh sách chưa sắp xếp | so sánh | Đã sắp xếpdanh sách |
---|---|---|---|
1 | {12,3,5,10,8,1} | {12,3} | {3,12,5,10,8,1} |
2 | {3,12,5,10,8,1} | {3,12,5} | {3,5,12,10,8,1} |
3 | { 3,5,12,10,8,1} | {3,5,12,10} | {3,5,10,12,8,1} |
4 | {3,5,10,12,8,1} | {3,5,10,12,8} | {3,5,8,10,12,1} |
5 | {3,5,8,10,12,1} | {3,5,8,10,12,1} | {1,3,5,8,10,12} |
6 | {} | {} | {1,3,5,8,10,12} |
Như minh họa trong minh họa ở trên, chúng ta bắt đầu với phần tử thứ 2 vì chúng ta giả sử rằng phần tử đầu tiên luôn được sắp xếp. Vì vậy, chúng tôi bắt đầu bằng việc so sánh phần tử thứ hai với phần tử thứ nhất và hoán đổi vị trí nếu phần tử thứ hai nhỏ hơn phần tử thứ nhất.
Quá trình so sánh và hoán đổi này đặt hai phần tử vào đúng vị trí của chúng. Tiếp theo, chúng tôi so sánh phần tử thứ ba với phần tử trước đó (thứ nhất và thứ hai) của nó và thực hiện quy trình tương tự để đặt phần tử thứ ba vào vị trí thích hợp.
Theo cách này, đối với mỗi lần vượt qua, chúng tôi đặt một phần tử vào Vị trí của nó. Đối với lần đầu tiên, chúng tôi đặt phần tử thứ hai vào vị trí của nó. Do đó, nói chung, để đặt N phần tử vào đúng vị trí của chúng, chúng ta cần N-1 lượt đi.
Tiếp theo, chúng ta sẽ trình bày cách triển khai kỹ thuật sắp xếp Chèn trong ngôn ngữ C++.
Ví dụ C++
#include using namespace std; int main () { int myarray[10] = { 12,4,3,1,15,45,33,21,10,2}; cout"\nInput list is \n"; for(int i=0;i10;i++) { cout="" Output:
Input list is
12 4 3 1 15 45 33 21 10 2
Sorted list is
1 2 3 4 10 12 15 21 33 45
Next, we will see the Java implementation of the Insertion sort technique.
Java Example
public class Main { public static void main(String[] args) { int[] myarray = {12,4,3,1,15,45,33,21,10,2}; System.out.println("Input list of elements ..."); for(int i=0;i10;i++) { System.out.print(myarray[i] + " "); } for(int k=1; k=0 && temp = myarray[j]) { myarray[j+1] = myarray[j]; j = j-1; } myarray[j+1] = temp; } System.out.println("\nsorted list of elements ..."); for(int i=0;i10;i++) { System.out.print(myarray[i] + " "); } } }Output:
Input list of elements …
12 4 3 1 15 45 33 21 10 2
sorted list of elements …
1 2 3 4 10 12 15 21 33 45
In both the implementations, we can see that we begin sorting from the 2nd element of the array (loop variable j = 1) and repeatedly compare the current element to all its previous elements and then sort the element to place it in its correct position if the current element is not in order with all its previous elements.
Insertion sort works the best and can be completed in fewer passes if the array is partially sorted. But as the list grows bigger, its performance decreases. Another advantage of Insertion sort is that it is a Stable sort which means it maintains the order of equal elements in the list.
Complexity Analysis Of The Insertion Sort Algorithm
From the pseudo code and the illustration above, insertion sort is the efficient algorithm when compared to bubble sort or selection sort. Instead of using for loop and present conditions, it uses a while loop that does not perform any more extra steps when the array is sorted.
However, even if we pass the sorted array to the Insertion sort technique, it will still execute the outer for loop thereby requiring n number of steps to sort an already sorted array. This makes the best time complexity of insertion sort a linear function of N where N is the number of elements in the array.
Thus the various complexities for Insertion sort technique are given below:
Worst case time complexity O(n 2 ) Best case time complexity O(n) Average time complexity O(n 2 ) Space complexity O(1) In spite of these complexities, we can still conclude that Insertion sort is the most efficient algorithm when compared with the other sorting techniques like Bubble sort and Selection sort.
Conclusion
Insertion sort is the most efficient of all the three techniques discussed so far. Here, we assume that the first element is sorted and then repeatedly compare every element to all its previous elements and then place the current element in its correct position in the array.
In this tutorial, while discussing Insertion sort we have noticed that we compare the elements using an increment of 1 and also they are contiguous. This feature results in requiring more passes to get the sorted list.
In our upcoming tutorial, we will discuss “Shell sort” which is an improvement over the Selection sort.
In shell sort, we introduce a variable known as “increment” or a “gap” using which we divide the list into sublists containing non-contiguous elements that “gap” apart. Shell sort requires fewer passes when compared to Insertion sort and is also faster.
In our future tutorials, we will learn about two sorting techniques, “Quicksort” and “Mergesort” which use “Divide and conquer” strategy for sorting data lists.