排序
启示|revelation
排序: 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次 序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排 序算法是稳定的;否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。
一、排序的运用
网上购物,假如我想买一台相机,于是去购物网站搜索。可是搜索后发现,有91万+商品,如此之多,如何选择?我其实是想买性价比高的,口碑好的,想找信誉好的商家,如何做?这里就需要用到排序了。
二、常见的排序算法
三、常见排序算法的实现、
1、冒泡排序
1、基本思想
冒泡排序(bubble sort)是一种交换排序,它的基本思想是:两两相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。
2、实现
//后续都会用到交换,封装成函数
void swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
//冒泡排序
void BubbleSort(int* a, int n)
{
int i = 0;
int j = 0;
for (i = 0; i < n - 1; i++)
{
//设计一个标志,如果没有进入循环说明后面已经有序,跳出循环
int exchange = 0;
for (j = 1; j < n - i; j++)
{
if (a[j] < a[j - 1])
{
swap(&a[j], &a[j - 1]);
exchange = 1;
}
}
if (exchange == 0)
{
break;
}
}
}
2、插入排序
1、基本思想
直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为 止,得到一个新的有序序列 。
实际中我们玩扑克牌时,就用了插入排序的思想
2、直接插入排序
当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与 array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移
void InsertSort(int* a, int n) { for (int i = 1; i < n; i++) { int end = i - 1, tmp = a[i]; while (end >= 0) { if (a[end] < tmp) { a[end + 1] = a[end]; end--; } else { break; } } a[end + 1] = tmp; } }
直接插入排序的特性总结:
- 元素集合越接近有序,直接插入排序算法的时间效率越高
- 时间复杂度:O(N^2)
- 空间复杂度:O(1),它是一种稳定的排序算法
- 稳定性:稳定
3、希尔排序
1、基本思想
希尔排序法又称缩小增量法。希尔排序是对直接插入排序的优化
1、先选定一个整数gap,把待排序数组中所以数据分成gap组。
2、所有距离为gap的数据分在同一组内,并对每一组内的数据进行排序,让数组接近有序。
3、取不同gap重复上述分组和排序。
2、实现
//希尔排序 void ShellSort(int* a, int n) { int gap = n; 第一种写法,循环层数多一层 用来控制循环 //int i = 0; //int j = 0; // //while (gap > 1) //{ // gap = gap / 3 + 1; // //最外层——分成几组预排序 // for (i = 0; i < gap; i++) // { // //进行一组的预排序 // for (j = 0; j < n - gap; j += gap) // { // int end = j; // int x = a[end + gap]; // while (end >= 0) // { // if (a[end] > x) // { // a[end + gap] = a[end]; // end -= gap; // } // else // { // break; // } // a[end + gap] = x; // } // } // } //} //第二种写法,一锅炖,比较简洁 //用来控制循环 int i = 0; //最外层——分成gap组预排序 while (gap > 1) { gap = gap / 3 + 1; //进行预排序 for (i = 0; i < n - gap; i++) { int end = i; int x = a[end + gap]; while (end >= 0) { if (a[end] > x) { a[end + gap] = a[end]; end -= gap; } else { break; } } a[end + gap] = x; } } }
end >= 0)
{ if (a[end] > x) { a[end + gap] = a[end]; end -= gap; } else { break; } } a[end + gap] = x; }
}
}