插入排序
1 直接插入排序
//直接插入排序
//1 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列
//2 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置
//3 如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面
void InsertDirectly(int *L, int len){
int i, j, temp;
for (i = 1; i < len; ++i){
j = i;
temp = L[i]; //临时变量存储待排序元素
//寻找待插位置:只要未到数组首位或者当前元素小于待排序元素,就将当前元素后移一位
while (j > 0 && temp < L[j-1]){
L[j] = L[j-1];
j--;
}
L[j] = temp; //插入位置已经找到,插入
}
}
2 折半插入排序
void InsertInHalf(int *L, int len){
int i, j, mid;
int low = 0, high = 0, temp = 0;
for (i = 1; i < len; ++i){
low = 0;
high = i - 1;
temp = L[i];
//使用折半查找定诶插入位置 low
while (low <= high){
mid = (low + high) / 2;
if (L[mid] > temp)
high = mid - 1;
else
low = mid + 1;
}
//带插入位置之后的元素统一后移
for (j = i; j > low; --j)
L[j] = L[j-1];
//插入元素
L[low] = temp;
}
}
3 希尔排序
//1 选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1
//2 按增量序列个数 k,对序列进行 k 趟排序
//3 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序
//4 仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度
void HillSort(int *L, int len){
for (int step = len / 2; step > 0; step /= 2) {
// i : 即将插入的元素的下标,作为每一组比较数据的最后一个元素下标
for (int i = step; i < len; ++i) {
// j : 与 i 为同一组的元素的下标
for (int j = i - step; j >= 0; j -= step) { //避免数组下标越界
if (L[j] > L[j + step]){ // L[j+step] 代表即将插入的元素
//符合条件,插入元素
int temp = L[j];
L[j] = L[j + step];
L[j + step] = temp;
}
}
}
}
}
交换排序
1 冒泡排序
//1 比较相邻的元素。如果第一个比第二个大,就交换他们两个
//2 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数
//3 针对所有的元素重复以上的步骤,除了最后一个
//4 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
void BubbleSort(int *L, int len){
for (int i = 0; i < len - 1; ++i) {
for (int j = 0; j < len - i - 1; ++j) {
if (L[j] < L[j - 1]){
int temp = L[j];
L[j] = L[j + 1];
L[j + 1] = temp;
}
}
}
}
2 快速排序
//1 从数列中挑出一个元素,称为 "基准"(pivot)
//2 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面
//3 在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作
//4 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序
void QuickSorted(int *L, int left, int right){
if (left > right)
return;
int temp = L[left];
int i = left, j = right;
while (i < j){
while (i < j && temp <= L[j])
j--;
if (i < j)
L[i++] = L[j];
while (i < j && temp > L[i])
i++;
if (i < j)
L[j--] = L[i];
}
L[i] = temp;
QuickSorted(L, left, i - 1);
QuickSorted(L, i + 1, right);
}
选择排序
1 简单选择排序
//1 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
//2 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾
//3 重复第二步,直到所有元素均排序完毕
void Swap(int *x, int *y){
int temp = *x;
*x = *y;
*y = temp;
}
void SelectSort(int *L, int len){
for (int i = 0; i < len - 1; ++i) {
int min = i;
for (int j = i + 1; j < len; ++j) //遍历未排序的元素
if (L[j] < L[min]) //找到目前的最小值
min = j; //记录最小值下标
Swap(&L[min], &L[i]); //交换
}
}
2 堆排序
//1 创建一个堆 H[0……n-1]
//2 把堆首(最大值)和堆尾互换
//3 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置
//4 重复步骤 2,直到堆的尺寸为 1
void Swap(int *x, int *y){
int temp = *x;
*x = *y;
*y = temp;
}
void MaxHeap(int *L, int start, int end){
//建立父节点与子节点指标
int dad = start;
int son = dad * 2 + 1;
//只有当子节点指标在范围内才进行比较
while (son <= end){
if (son + 1 <= end && L[son] < L[son + 1]) //选择两个子节点中最大的
son++;
if (L[dad] > L[son]) //父节点大于自己诶单代表调整完毕,跳出函数
return;
else{ //否则,交换父子内容后,再继续进行子节点和孙子结点的比较
Swap(&L[dad], &L[son]);
dad = son;
son = dad * 2 + 1;
}
}
}
void HeapSort(int *L, int len){
// 从最后一个父节点开始调整
int i;
for (i = len / 2 - 1; i >= 0; --i)
MaxHeap(L, i, len - 1);
//先将第一个元素和已经排序完毕的元素前一位进行交换,再重新调整,直至排序结束
for (i = len - 1; i > 0; --i){
Swap(&L[0], &L[i]);
MaxHeap(L, 0, i - 1);
}
}
3 二路归并排序
//1 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
//2 设定两个指针,最初位置分别为两个已经排序序列的起始位置
//3 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
//4 重复步骤 3 直到某一指针达到序列尾
//5 将另一序列剩下的所有元素直接复制到合并序列尾
int min(int x, int y){
return x < y ? x : y;
}
void MergeSort(int *L, int len){
int *a =L;
int *b = (int *)malloc(sizeof(int) * len);
int seg, start;
for (seg = 1; seg < len; seg += seg){
for (start = 0; start < len; start += seg * 2){
int low = start;
int mid = min(start + seg, len);
int high = min(start + seg * 2, len);
int k = low;
int start1 = low, end1 = mid;
int start2 = mid, end2 = high;
while (start1 < end1 && start2 < end2)
b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
while (start1 < end1)
b[k++] = a[start1++];
while (start2 < end2)
b[k++] = a[start2++];
}
int *temp = a;
a = b;
b = temp;
}
if (a != L){
int i;
for (i = 0; i < len; i++)
b[i] = a[i];
b = a;
}
free(b);
}
4 基数排序
#define MaxSize 100
#define Base 10
void BaseSort(int *a, int len){
int i, b[MaxSize], m = a[0], exp = 1;
for (i = 1; i < len; i++) {
if (a[i] > m) {
m = a[i];
}
}
while (m / exp > 0) {
int bucket[Base] = { 0 };
for (i = 0; i < len; i++) {
bucket[(a[i] / exp) % Base]++;
}
for (i = 1; i < Base; i++) {
bucket[i] += bucket[i - 1];
}
for (i = len - 1; i >= 0; i--) {
b[--bucket[(a[i] / exp) % Base]] = a[i];
}
for (i = 0; i < len; i++) {
a[i] = b[i];
}
exp *= Base;
}
}