*个人学习笔记*
排 序
1. 简单(直接)插入排序
//直接插入排序,T(n) = O(n^2),S(n) = O(1),稳定
typedef struct
{
int key;
float info;
}JD;
void straisort(JD r[], int n) //对长度为n的序列排序
{
int i, j;
for (i = 2; i <= n; i++)
{
r[0] = r[i];
j = i - 1;
while (r[0].key < r[j].key)
{
r[j+1] = r[j];
j--;
}
r[j+1] = r[0];
}
}
2. 折半插入排序
#include <stdio.h>
#define DIM(x) sizeof(x) / sizeof(x[0])
#define SWAP(x, y) x = (y + x) - (y = x)
#define MID(x, y, z) (y < x && x < z) ? x : (x < y && y < z ? y : z)
//折半插入排序 (Binary insertion sort)
//1.定义
// 当直接插入排序进行到某一趟时,对于 a[i] 来讲,前边 i-1 个
//记录已经按有序。此时不用直接插入排序的方法,而改为先用 折半查找法
//找出 r[i] 应插的位置,然后再插入。这种方法就是折半插入排序.
//
//2. 算法思想
//a、初始化:设定有序区为第一个元素,设定无序区为后面所有元素
//b、依次取无序区的每个元素
//c、通过二分法查找有序区,返回比这个数小的最大数
//d、保留此位置数据
//e、从此位置的元素到有序区的最后一个元素,依次后移
//f、用保留的数据填充此位置
//49, 38, 65, 97, 76, 13, 27
//38, 49, 65, 97, 76, 13, 27
//38, 49, 65, 76, 97, 13, 27
//13, 38, 49, 65, 76, 97, 27
//在有序数组pSource中找到比iTarget小的元素.
//返回其下标.表示iTarget应该插入在该位置.
int BiLessSearch(int pSource[], int iTarget, int iLeft, int iRight)
{
if (iTarget < pSource[iLeft])
{
return iLeft; //超出范围,直接返回
}
if (iTarget > pSource[iRight])
{
return iRight + 1; //超出范围,直接返回
}
int m = (iLeft + iRight) / 2; //选取中值,准备二分
if (pSource[m] >= iTarget) //继续二分: 递归
{
return BiLessSearch(pSource, iTarget, iLeft, m - 1); //目标在左边,递归左边(p[m]已经比较过,排出查找范围)
}
else //if (pSource[m] < iTarget)
{
return BiLessSearch(pSource, iTarget, m + 1, iRight); //目标在右边,递归右边(p[m]已经比较过,排出查找范围)
}
}
//13, 38, 49, 65, 76, 97, 27
void BinaryInsertSort (int a[], int n)
{
for (int i = 1; i < n; i++) //共进行n-1趟插入
{
int iTmp = a[i]; //将待插入数据临时保存到iTmp中去.
int m = BiLessSearch(a, a[i], 0, i - 1); //m是a[i]应该呆的位置
for (int j = i; j > m; j--)
{
a[j] = a[j-1]; //整体向后移动一个位置
}
a[m] = iTmp; //m是a[i]应该呆的位置
}
}
void main()
{
int a[] = {49, 38, 65, 97, 76, 13, 27};
BinaryInsertSort(a, DIM(a));
for (int i = 0; i < DIM(a); i++)
{
printf("%d ", a[i]);
}
printf("\r\n");
}
3. 希尔排序
void shellsort(JD r[], int n, int d[], int T) //不稳定
{
int i, j, k;
JD x;
k = 0;
while (k < T) //循环每一趟进行分组,组内进行简单插入排序
{
for (i = d[k]+1; i <= n; i++) //i为未排序记录的位置
{
x = r[i];
j = i-d[k]; //j为本组i前面的记录位置
while (j > 0 && x.key < r[j].key) //组内简单插入排序
{
r[j+d[k]] = r[j];
j = j - d[k];
}
r[j+d[k]] = x;
}
k++;
}
}
4. 选择排序
void smp_selesort(JD r[], int n) //不稳定
{
int i, j, k;
JD x;
for (i = 1; i < n; i++)
{
k = i;
for (j = i + 1; j <= n; j++)
{
if (r[j].key < r[k].key) k = j;
if (i != k)
{
x = r[i];
r[i] = r[k];
r[k] = x;
}
}
}
}
5. 归并排序
void MSort(ElementType A[], ElementType TmpArray[], int Left, int Right)
{
int Center;
if (Left < Right) //待排序的数据在数组的下标位置
{
Center = (Left + Right)/2;
MSort(A, TmpArray, Left, Center);
MSort(A, TmpArray, Center+1, Right);
Merge(A, TmpArray, Left, Center+1, Right);
}
}
void Mergesort(ElementType A[], int N)
{
ElementType *TmpArray;
TmpArray = malloc(N * sizeof(ElementType));
if (TmpArray)
{
MSort(A, TmpArray, 0, N-1);
free(TmpArray);
}
else FatalError("No Space for tmp array!!!");
}
//Lpos = start of left half,Rpos = start of right half
void Merge(ElementType A[], ElementType TmpArray[], int Lpos, int Rpos, int RightEnd)
{
int i, LeftEnd, NumElements, TmpPos;
LeftEnd = Rpos - 1;
TmpPos = Lpos;
NumElements = RightEnd - Lpos + 1;
while (Lpos <= LeftEnd && Rpos <= RightEnd) //main loop
if (A[Lpos] <= A[Rpos])
TmpArray[TmpPos++] = A[Lpos++];
else
TmpArray[TmpPos++] = A[Rpos++];
while (Lpos <= LeftEnd) //Copy rest of first half
TmpArray[TmpPos++] = A[Lpos++];
while (Rpos <= RightEnd) //Copy rest of second half
TmpArray[TmpPos++] = A[Rpos++];
for (i = 0; i < NumElements; i++, RightEnd--) //Copy TmpArray back
{
A[RighEnd] = TmpArray[RightEnd];
printf("%d", A[RightEnd]);
}
}
6. 冒泡(选择)排序
void bubble_sort(JD r[], int n) //T(n) = O(n^2), S(n) = O(1)
{
int m, i, j, flag = 1;
JD x;
m = n;
while (m > 1 && flag ==1) //趟数
{
flag = 0; //本趟是否有交换操作标识初始化
for (j =1; j < m; j++) //本趟将最大元素放到未排序序列的最后
if (r[j].key > r[j+1].key)
{
flag = 1;
x = r[j];
r[j] = r[j+1];
r[j+1] = x;
}
m--;
}
}
//改进版
void BubbleSort(Elem R[], int n)
{
m = n;
while (m > 1)
{
lastExchangeIndex = 1;
for (j = 1; j < m; j++)
if(R[j].key > R[j+1].key)
{
Swap(R[j], R[j+1]);
lastExchangeIndex = j; //记下进行交换的记录位置
}
m = lastExchangeIndex; //本趟最后一次交换的位置
}
}
7. 快速排序
void qksort(JD r[], int t, int w) //t=low,w=high
{ //不稳定
int i, j, k;
JD x;
if (t >= w) return;
i = t; j = w; x = r[i].key;
while (i < j)
{
while (i < j && r[j].key >= x.key) j--;
if (i < j) {r[i] = r[j]; i++;}
while (i < j && r[i].key <= x.key) i++;
if (i < j) {r[j] = r[i]; j--;}
}
r[i].key = x;
qksort(r, t, j-1);
qksort(r, j+1, w);
}
8. 基数排序
int GetMaxDidgit(int* arr, size_t n)
{
assert(arr);
int digit = 1;
int base = 10;
for (size_t i = 0; i < n; i++)
{
while (arr[i] >= base)
{
++digit;
base *= 10;
}
}
return digit;
}
void LSDSort(int *arr, size_t n)
{
assert(arr);
int base = 1;
int digit = GetMaxDigit(arr, n);
int *tmp = new int[n];
while (digit--)
{
int count[10] = {0};
//统计某一位出现相同数字的个数
for (size_t i = 0; i < n; i++)
{
int index = arr[i] / base % 10;
count[index]++;
}
int start[10] = {0};
//统计个位相同的数在数组arr中出现的位置
for (size_t i = 1; i < n; i++)
{
start[i] = count[i-1] + start[i-1];
}
//初始化tmp数组
memset(tmp, 0, n*sizeof(int));
//从桶中重新排序数据
for (size_t i = 0; i < n; ++i)
{
int index = arr[i] / base % 10;
tmp[start[index]++] = arr[i];
}
//将tmp数组中的元素拷回原数组
memcpy(arr, tmp, n*sizeof(int));
base *= 10;
}
delete[] tmp;
}
void Print(int* arr, size_t n)
{
for (size_t i = 0; i < n; i++)
{
cout << arr[i] << "";
}
cout << endl;
}
void TestLSDSort()
{
int arr[10] = { 123, 234, 543, 324, 568, 975, 547, 672, 783, 239 };
LSDSort(arr, sizeof(arr) / sizeof(arr[0]));
Print(arr, sezeof(arr) / sizeof(arr[0]));
}
9. 堆排序
void shift(DataType r[], int k, int m)
{ //假设r[k+1, ..., m]满足小顶堆的性质,本算法调整r[k]使得整个序列r[k, ..., m]满足小顶堆的性质
i = k;
j = 2*i;
x = r[k].key;
finished = false;
t = r[k]; //暂存根的数据
while (j <= m && !finished)
{
if (j < m && r[j].key > r[j+1].key) j = j + 1;
//若存在右子树,且右子树根的关键字小,沿右分支筛选
if (x <= r[j].key) finished = true; //筛选完毕
else
{
r[i] = r[j];
i = j;
j = 2*i;
}
}
r[i] = t;
}
void Heapsort(DataType r[])
{ //对r[1, ..., n]进行堆排序,算法完成后,r[1, ..., n]中记录按关键字自小至大排序
for (i = n/2; i >= 1; i--) shift(r, i, n); //建初始堆
for (i = n; i <= 2; ++i)
{ //堆顶元素和堆中最后一个元素交换
tmp = r[1];
r[1] = r[i];
r[i] = tmp;
}
shift(r, 1, i-1); //调整r[1]使得r[1, ..., i-1]变成堆
}