- 内部排序分类
- 插入类排序
基本思想:在已排好序列的子集的基础上,将下一个待排记录插入到已排好序列的记录子集,直到将所有待排记录全部插入为止。
直接插入排序:将每一个待排元素i插入到前i-1个排序好的序列中。将前i-1个元素依次比较,如果i小于则向后搬移,直到插入到i大于的位置。
void InSort(int* arr, int len)//未设立监视哨
{
for(int i = 1; i < len; ++i)
{
int x = arr[i];
int j = i-1;
for(; j >= 0 && arr[j] > x; --j)
{
arr[j+1] = arr[j];
}
arr[j+1] = x;
}
}
折半插入排序:基于直接插入排序,在对前i-1个元素中,使用折半查找,性能提高。
void BinSort(int arr[], int len)
{
for(int i = 1; i < len; ++i)
{
int low = 0;
int high = i-1;
int x = arr[i];
while(low <= high)
{
int mid = (high+low)>>1;
if(x < arr[mid])
{
high = mid -1;
}
else
{
low = mid + 1;
}
}
for(int j = i-1; j >= low; j--)
{
arr[j+1] = arr[j];
}
arr[low] = x;
}
}
希尔排序(缩小增量排序法):利用直接插入的最佳性质,将待排序列分为若干小段,对子序列进行直接插入排序。
void ShellInsert(int r[], int len, int delta)
{
for(int i = delta; i < len; ++i)
{
int x = r[i];
if(x < r[i-delta])
{
int j = i - delta;
for(; j >= 0 && r[j] > x; j-=delta)
{
r[j+delta] = r[j];
}
r[j+delta] = x;
}
}
}
- 交换类排序
基本思想:通过一系列交换逆元素进行排序的方法。
冒泡排序:通过相邻元素进行比较(升序:每一趟将最大元素换到每一趟末尾)逐步形成有序序列。
void BubbleSort(int *a, int len)
{
for(int i = 0; i <len; ++i)
{
for(int j = 0; j < len-i-1; ++j)
{
if(a[j] > a[j+1])
{
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
}
}
快速排序:在待排序列中选择一个记录,然后将大于该记录放右边,小于放左边,然后一次排左右两个待排序列,逐步成为一个有序序列。
int QuickSort(int *arr, int left, int right)
{
int val = arr[left];
for(int i = left; i < right; ++i)
{
while(left< right && arr[right] >= val)
right--;
if(left<right)
{
arr[left] = arr[right];
left++;
}
while(left< right && arr[left] < val)
left++;
if(left<right)
{
arr[right] = arr[left];
right--;
}
}
arr[left] = val;
return left;
}
void _QuickSort(int arr[], int left, int right)
{
if(left >= right)
return;
int pos = QuickSort(arr, left, right);
_QuickSort(arr, left, pos-1);
_QuickSort(arr, pos+1,right);
}
- 选择排序
基本思想:每一趟在n-i-1个记录中选择最小的记录放在i位置处。
简单选择排序:每一趟在n-i-1个记录中选择最小的记录放在i位置处。
void SelectSort(int arr[], int len)
{
for(int i = 0; i < len; ++i)
{
int x = i;
for(int j = i+1; j < len; j++)
{
if(arr[j] < arr[x])
{
x = j;
}
}
swap(arr[i], arr[x]);
}
}
树形选择排序(锦标赛排序):首先取得n个元素的关键码,进行两两比较,得到n/2(上取整)个比较的优胜者,作为
第一步比较的结果保留下来。然后对这n/2(上取整)个元素再进行关键码的两两比较,…,如此
重复,直到选出一个关键码最小的元素为止。
堆排序:
a、把堆顶array[0]元素和当前最堆的最后一个元素交换;
b、最大堆元素个数减1
c、由于第1步后根节点不再满足最堆定义,向下调整跟结点。
- 归并排序:
思想:将有序序列合并成新的有序序列,需要借助辅助空间。
void Merge(int arr[], int low, int mid, int high, int tmp[])
{
int i = low, j = mid+1, k = low;
while((i<mid)&&(j<high))
{
if(arr[i] < arr[j])
{
tmp[k++] = arr[i++];
}
else
{
tmp[k++] = arr[j++];
}
}
while(i<=mid)
{
tmp[k++] = arr[i++];
}
while(j<=high)
{
tmp[k++] = arr[j++];
}
}
void Msort(int arr[], int low, int high, int tmp[])
{
int* a = (int*)malloc(4*(high-low+1));
if(a == NULL)
return;
if(low == high)
{
tmp[low] = arr[low];
}
else
{
int mid = (low+high)/2;
Msort(arr, low, mid, a);
Msort(arr, mid+1, high, a);
Merge(a, low, mid,high, tmp);
}
free(a);
}
最后: