1.冒泡排序
1.冒泡排序的原理是:从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。
以从小到大排序为例,第一轮比较后,所有数中最大的那个数就会浮到最右边;第二轮比较后,所有数中第二大的那个数就会浮到倒数第二个位置……就这样一轮一轮地比较,最后实现从小到大排序。每次排序的元素都会减少,直到没有任何一队元素需要比较。
比较时,每轮中第 n 次比较是新序列中第 n 个元素和第 n+1 个元素的比较(假如 n 从 1 开始)
时间复杂度:
最好情况:是有序的,只需遍历一遍即可 O(n)
最坏情况:全部无序,每次都要交换 O(n*2)
#include<stdio.h>
#include<assert.h>
//冒泡排序 -->每次确定一个最大的
void BubbleSort(int *a, int n)
{
assert(a);
for (size_t i = 0; i < n - 1; i++)//比较n-1轮,最后一个不需要比较
{
int exchange = 0;//设置一个标志位
for (size_t j = 0; j < n - 1 - i; j++)//每一轮比较n-1-i次,每一轮少比较1次
{
if (a[j]>a[j + 1])//从小到大排序
{
//swap(&a[j], &a[j + 1]);//交换
size_t tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
exchange = 1;
}
}
if (exchange == 0)//若没有发生交换,则直接退出,优化
break;
}
}
int main()
{
int a[10] = { 5, 88, 23, 14 };
BubbleSort(a, 4);
return 0;
}
2.二分查找(折半查找)
一个有序序列的高效查找算法
实现思路:
int mid = begin + ((end - begin) >> 1)
这样是防止溢出的写法(记住就好)
int BinarySearch(int *a, int n, int x)
{
assert(a);
int begin = 0;
int end = n - 1;
while (begin <= end)//两个相等时,判断的是最后一位
{
int mid = begin + ((end - begin) >> 1);
if (a[mid] < x)
{
begin = mid + 1;
}
else if (a[mid]>x)
{
end = mid - 1;
}
else
return mid;
}
return -1;//查找失败
}
int main()
{
int a[100] = { 1,3,4,6,7,8,10,13,14 };
BinarySearch(a, 9, 4);
printf("%d", BinarySearch(a, 9, 4));
}
3.插入排序
**思想:**直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
实际中我们玩扑克牌时,就用了插入排序的思想。
当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。
直接插入排序的特性总结:
- 元素集合越接近有序,直接插入排序算法的时间效率越高
- 时间复杂度:O(N^2)
- 空间复杂度:O(1),它是一种稳定的排序算法
- 稳定性:稳定
有序位置的最后一个位置向前遍历,找到第一个小于待插数据的位置,然后这个数据放入已经找到位置的下一个位置
代码实现:
void InsertSort(int* a, int lenth)
{
int i, j, z, index;
for (j = 1; j < lenth; j++)//待插入数据 从1开始 首元素为初始有序数列
{
for (i = j - 1; i >= 0; i--)//已排序数据
{
if (a[j] > a[i])//在已排序列中找到位置
{
break;
}
}
index = a[j];//将待插入数据拷贝出来等待 下面数据后移时会覆盖该数据
if (i != j - 1)//不是有序数据末尾
{
for (z = j; z > i; z--)//数据后移,留出待插空位
{
a[z] = a[z - 1];
}
a[i + 1] = index;
}
}
}
void InsertSort(int* a, int lenth)
{
//假设第一个数据有序
//要拍的[1,n)
for (int i = 1; i < lenth; ++i)//代排的
{
int end = i - 1;
int data = a[i];
while (end >= 0 && a[end] >= data)
{
a[end + 1] = a[end];//大的向后移动
--end;
}//end=-1时退出
a[end + 1] = data;//end位置是比待排数据要小的,
}
}