文章目录
冒泡排序 (Bubble Sort)
1.基本思想 :
从无序序列头部开始,进行两两比较,根据大小交换位置,知道最>后将大(小)的数据元素交换到无需队列的队尾,从而成为有序列表的一部分;下一次继续这个过程,直到所有数据元素都排好序
2.运行过程
冒泡排序算法的运作如下:
(1)比较相邻的元素。比如第一个比第二个大(小),就交换它们两个。
(2)对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大(小)的数。
(3)针对所有的元素重复以上的步骤,除了最后已选出的元素(有序)。
(4)持续每次对越来越少的元素(无序元素)重复上面的步骤,直到没有任何一对数字需>要比较,则序列最终有序。
一趟排序:
下标 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
value | 5 | 3 | 2 | 4 | 1 |
下标 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
value | 5 | 3 | 2 | 1 | 4 |
下标 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
value | 5 | 3 | 1 | 2 | 4 |
下标 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
value | 5 | 1 | 3 | 2 | 4 |
下标 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
value | 1 | 5 | 3 | 2 | 4 |
3.算法实现( 核心代码 )
void BubbleSort(int a[],int n)
{
for(int i = n-1; i; i--) // n- 1轮冒泡
for(int j = 0; j < i; j++) //每轮进行 i 次比较
if(a[j] > a[j+1]) //逆序
swap(a[j], a[j+1]); //交换
}
public int[] bubbleSort(int[] A, int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (A[j] > A[j + 1]) {
int temp = A[j];
A[j] = A[j + 1];
A[j + 1] = temp;
}
}
}
return A;
}
冒泡排序法中的交互次数又称为反序数或逆序数,体现数据的错乱程度。
bool ok = true;
int i=0,num=0; // i:表示未排序部分的开头元素,从数组开头向末尾移动
while(ok){
ok = false;
for(int j = N - 1; j >= i + 1; j--){
// j:表示对未排序部分中的相邻元素两两比较,
//从 a[] 末尾 N - 1 开始,减少到 i + 1 结束
if(a[j] < a[j-1]){
//与上述代码相反,这个将最小值从后面往前移动,固定最小值
swap(a[j], a[j-1]);
num++; //记录交换次数
ok=true;
}
}
}
冒泡排序仅对数组中的相邻元素进行比较和交换,因此键相同的元素不会改变顺序,因此是稳定的排序算法。但是如果将 A [ j ] < A [ j − 1 ] A[j] < A[j-1] A[j]<A[j−1] 改成 A [ j ] A[j] A[j] ≤ \leq ≤ A [ j − 1 ] A[j-1] A[j−1],算法失去稳定性。假设数据量是 N N N,对未排序部分的相邻元素进行 ( N − 1 ) + ( N − 2 ) + ⋯ + 1 = ( N 2 − N ) 2 (N-1) + (N-2) + \cdots +1 = \frac{(N^2-N)}{2} (N−1)+(N−2)+⋯+1=2(N2−N),所有时间复杂度最坏情况是 ( N 2 ) (N^2) (N2)
选择排序 (Selection Sort)
1.基本思想
对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小(大)则用一个变量k来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较,如果后面的元素比他要小(大)则用变量k记住它在数组中的位置(下标),等到循环结束的时候,我们应该找到了最小(大)的那个数的下标了,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小(大)的数了。然后找到数组中第二小(大)的数,让他跟数组中第二个元素交换一下值,以此类推。
2.运行过程
(1)定义一个变量tmp记录待替换元素位置。
(2)比较待替换元素与当前元素的位置;若待替换元素大(小),则将tmp下标移到当前元素
(3)待替换元素与其后所有元素比较结束之后,交换待替换元素和tmp下标所记录的元素位置
(4)针对每一个元素重复以上操作,直到所有元素都有序。
下标 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
value | 3H | 5S | 3D | 1S |
下标 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
value | 1S | 5S | 3D | 3H |
下标 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
value | 1S | 3D | 5S | 3H |
下标 | 0 | 1 | 2 | 3 |
---|---|---|---|---|
value | 1S | 3D | 3H | 5S |
3.算法实现(核心代码)
void selectsort(int a[],int n)
{
int pos,sw=0; //pos存未排序部分最小值的下标
for(int i = 0; i < n-1; i++)
{
pos=i;
for(int j = i + 1; j < N; j++)
if(a[j] < a[pos]) pos = j;
if(i != pos) sw++,swap(a[i],a[pos])
}
return sw; //返回的交换次数
}
public static int[] selectionSort(int[] A) {
for (int i = 0; i < A.length - 1; ++i) {
int tmp = i;
for (int j = i + 1; j < A.length; ++j) {
if (A[tmp] > A[j])
tmp = j;
}
if (tmp != i) {
int temp = A[tmp];
A[tmp] = A[i];
A[i] = temp;
}
}
return A;
}
选择排序会直接交换两个不相邻的元素,所以属于不稳定的排序算法。假设数据是 N N N,选择排序算法需要进行 ( N − 1 ) + ( N − 2 ) + ⋯ + 1 = ( N 2 − N ) 2 (N-1) + (N-2) + \cdots + 1 = \frac{(N^2-N)}{2} (N−1)+(N−2)+⋯+1=2(N2−N) 次运算,用于搜索未排序部分的最小值,时间复杂度 O ( N 2 ) O(N^2) O(N2)。
判断稳定性,时间复杂度 O ( N 4 ) O(N^4) O(N4)
bool Check(int in[],int out[],int N)
{
for(int i = 0; i < N; i++)
for(int j = i + 1; j < N; j++)
for(int a = 0; a < N; a++)
for(int b = a + 1; b < N; b++)
if(in[i] == out[j] && in[i] == out[b] && in[j] == out[a])
return false;
return true;
}
插入排序(Insertion Sort)
1.基本思想
每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的元素中适当位置上,直到全部插入完为止。
2.运行过程
(1)从第一个元素开始,该元素可以认为已经被排序。
(2)取出下一个元素,在已经排序的元素序列中