1.气泡排序
冒泡排序在每个遍历中反复比较并交换(如果需要)相邻元素。在冒泡排序的第i次传递(升序)中,最后(i-1)个元素已被排序,第i个最大元素被放置在第(Ni)个位置,即第i个最后一个位置。
算法:
BubbleSort (Arr, N) // Arr is an array of size N.
{
For ( I:= 1 to (N-1) ) // N elements => (N-1) pass
{
// Swap adjacent elements of Arr[1:(N-I)]such that
// largest among { Arr[1], Arr[2], ..., Arr[N-I] } reaches to Arr[N-I]
For ( J:= 1 to (N-I) ) // Execute the pass
{
If ( Arr [J] > Arr[J+1] )
Swap( Arr[j], Arr[J+1] );
}
}
}
算法优化:检查内部循环(通过执行循环)中是否发生任何交换操作。如果没有任何交换,则意味着该数组现在已完全排序,因此无需继续,请停止排序操作。因此,当数组在所有遍完成之前进行排序时,我们可以优化遍数。并且它还可以在第一遍中检测给定的/输入数组是否已排序。
BubbleSort (Arr, N) // Arr is an array of size N.
{
For ( I:= 1 to (N-1) ) // N elements => (N-1) pass
{
// Swap adjacent elements of Arr[1:(N-I)]such that
// largest among { Arr[1], Arr[2], ..., Arr[N-I] } reaches to Arr[N-I]
noSwap = true; // Check occurrence of swapping in inner loop
For ( J:= 1 to (N-I) ) // Execute the pass
{
If ( Arr [J] > Arr[J+1] )
{
Swap( Arr[j], Arr[J+1] );
noSwap = false;
}
}
If (noSwap) // exit the loop
break;
}
}
时间复杂度:
- Best Case Sorted数组作为输入。或几乎所有元素都放在适当的位置。 [ O(N) ]。 O(1)交换。
- 最坏的情况:反向排序/很少有元素放置在适当的位置。 [ O(N 2 ) ]。 O(N 2 )互换。
- 平均情况:[ O(N 2 ) ]。 O(N 2 )互换。
空间复杂度:在交换[辅助O(1) ]时使用了一个临时变量。因此,它是就地排序。
优势:
- 这是最简单的排序方法。
- 排序数组时,最佳情况的复杂度为O(N) (用于优化方法)。
- 使用优化的方法,它可以以O(1)的时间复杂度在第一遍中检测已经排序的数组。
- 稳定排序:不更改具有相同键的元素的相对顺序。
- 就地排序。
缺点:
- 气泡排序是相对较慢的算法。
2.选择排序
选择排序选择第i个最小元素并将其放置在第i个位置。该算法将数组分为两部分:已排序(左)和未排序(右)子数组。它从未排序的子数组中选择最小的元素,并将其放在该子数组的第一个位置(升序)。反复选择下一个最小的元素。
算法:
SelectionSort (Arr, N) // Arr is an array of size N.
{
For ( I:= 1 to (N-1) ) // N elements => (N-1) pass
{
// I=N is ignored, Arr[N] is already at proper place.
// Arr[1:(I-1)] is sorted subarray, Arr[I:N] is undorted subarray
// smallest among { Arr[I], Arr[I+1], Arr[I+2], ..., Arr[N] } is at place min_index
min_index = I;
For ( J:= I+1 to N ) // Search Unsorted Subarray (Right lalf)
{
If ( Arr [J] < Arr[min_index] )
min_index = J; // Current minimum
}
// Swap I-th smallest element with current I-th place element
If (min_Index != I)
Swap ( Arr[I], Arr[min_index] );
}
}
时间复杂度:
- 最佳情况[ O(N 2 ) ]。和O(1)交换。
- 最坏的情况:反向排序,当内部循环进行最大比较时。 [ O(N 2 ) ]。另外, O(N)交换。
- 平均情况:[ O(N 2 ) ]。还进行O(N)交换。
空间复杂度:[辅助, O(1) ]。就地排序。
优势:
- 它也可以用于使添加和删除有效的列表结构,例如链表。只需删除未排序部分的最小元素,然后在已排序部分的末尾结束即可。
- 掉期数量减少。在所有情况下O(N)交换。
- 就地排序。
缺点:
- 在所有情况下,时间复杂度均为O(N 2 ) ,没有最佳情况。
3.插入排序
插入排序是一种基于比较的简单排序算法。它将每个数组元素插入其正确位置。在第i次迭代中,先前的(i-1)个元素(即子数组Arr [1:(i-1)])已经排序,并且第i个元素(Arr [i])插入到它的适当位置先前排序的子数组。
在此GFG链接中查找更多详细信息。
算法:
InsertionSort (Arr, N) // Arr is an array of size N.
{
For ( I:= 2 to N ) // N elements => (N-1) pass
{
// Pass 1 is trivially sorted, hence not considered
// Subarray { Arr[1], Arr[2], ..., Arr[I-I] } is already sorted
insert_at = I; // Find suitable position insert_at, for Arr[I]
// Move subarray Arr [ insert_at: I-1 ] to one position right
item = Arr[I]; J=I-1;
While ( J ? 1 && item < Arr[J] )
{
Arr[J+1] = Arr[J]; // Move to right
// insert_at = J;
J--;
}
insert_at = J+1; // Insert at proper position
Arr[insert_at] = item; // Arr[J+1] = item;
}
}
}
时间复杂度:
- 最佳情况排序数组作为输入[ O(N) ]。和O(1)交换。
- 最坏的情况:反向排序,当内部循环进行最大比较时,[ O(N 2 ) ]。和O(N 2 )交换。
- 平均情况:[ O(N 2 ) ]。和O(N 2 )交换。
空间复杂度:[辅助, O(1) ]。就地排序。
优势:
- 它可以很容易地计算出来。
- 数组已排序时,最佳情况下的复杂度为O(N)。
- 交换数量比泡沫排序减少了。
- 对于较小的N值,插入排序会像其他二次排序算法一样高效执行。
- 排序稳定。
- 自适应的:减少了部分排序数组的步骤总数。
- 就地排序。
缺点:
- 通常在N值较小时使用。对于较大的N值,它的效率很低。
时空复杂度:
Sorting Algorithm | Time Complexity | Space Complexity | ||
---|---|---|---|---|
Best Case | Average Case | Worst Case | Worst Case | |
Bubble Sort | O(N) | O(N2) | O(N2) | O(1) |
Selection Sort | O(N2) | O(N2) | O(N2) | O(1) |
Insertion Sort | O(N) | O(N2) | O(N2) | O(1) |