二分查找方式的排序
- 有数数组
- 平衡二叉树:时间复杂度O(log2n)
AVL
红黑树 - 平衡多路搜索树
B树
B+树 - 多层有序列表
跳表结构
排序算法简介
十一种排序
下图是传统的十一种排序的对比情况。
暴力做法
冒泡:
不断比较相邻两个数据将其排序放置,
选择:
找到最小/最大的数据将其放到前面。
插入
元素越少,排序效率越高
数组越接近有序,排序效率越高
希尔排序
时间复杂度:O(n^1.5)
利用插入排序的特性,分组进行插入排序
不停的分组,让插入排序越发的快捷,从而达到了优化插入排序的目的
//从前往后插入排序
int shell_sort_font(int *data, int length)
{
int gap = 0;
int i = 0, j = 0;
int temp;
//分组
for (gap=length/2; gap>=1; gap/=2)
{
//计算到每个组
for(i=0; i<gap; i++)
{
//每组插入排序
temp = data[i];
for(j=i+gap; j<length && data[j] <= temp; j+=gap)
{
data[j-gap] = data[j];
}
data[j-gap] = temp;
}
}
}
//从后往前插入排序
int shell_sort(int *data, int length) {
int gap = 0; //分组的跨度
int i = 0, j = 0;
for (gap = length / 2; gap >= 1;gap /= 2) { // 分组的次数
for(i = gap; i < length; i ++) { // 每组遍历
int temp = data[i];
for (j = i - gap; j >= 0 && temp < data[j];j = j - gap) { //组内排序
data[j+gap] = data[j];
}
data[j+gap] = temp;
}
}
return 0;
}
归并排序
采用分治理念,进行递归排序。
void merge(int a[],int l,int r,int mid)
{
int aux[r-l+1],i,j,k;
for(k=l;k<=r;k++)
aux[k-l]=a[k];
i=l;
j=mid+1;
for(k=l;k<=r;k++)
{
if(i>mid)
{
a[k]=aux[j-l];
j++;
}
else if(j>r)
{
a[k]=aux[i-l];
i++;
}
else if(aux[i-l]>aux[j-l])
{
a[k]=aux[j-l];
j++;
}
else
{
a[k]=aux[i-l];
i++;
}
}
}
void merge_sort(int a[],int l,int r)
{
if(l>=r)
return ;
int mid=(l+r)/2;
merge_sort(a,l,mid);
merge_sort(a,mid+1,r);
merge(a,l,r,mid);
}
void merge_sort2(int a[], int len)
{
int i,j,k;
int step;
for(i=1;i<=len/2;i<<=1)
{
k=0;
step = i*2;
for(j=0;j<len-step; j+=step)
{
merge(a,j,j+step-1,(j+j+step-1)/2);
}
if(j<len)
{
merge(a,j,len-1,(j+len-1)/2);
}
}
}
快速排序
寻找一个基准值,将比他大的数据跟比他小的数据放到它的两边
int quick_sort(int *data, int length)
{
int *temp = 0;
int standard = data[0];
int i,j,k;
if(length <= 1)
{
return 0;
}
temp = calloc(length, sizeof(int));
for(i=1,j=0,k=length-1; i<length; i++)
{
if(standard < data[i])
{
temp[k--] = data[i];
}
else
{
temp[j++] = data[i];
}
}
temp[j] = standard;
memcpy(data, temp, length*sizeof(int));
free(temp);
quick_sort(data,j);
quick_sort(data+j+1,length-j-1);
}
堆排序
暂不理解,贴上代码,后续补齐相关知识点
void swap(int *a, int *b) {
int temp = *b;
*b = *a;
*a = temp;
}
void max_heapify(int arr[], int start, int end) {
// 建立父節點指標和子節點指標
int dad = start;
int son = dad * 2 + 1;
while (son <= end) { // 若子節點指標在範圍內才做比較
if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的
son++;
if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數
return;
else { // 否則交換父子內容再繼續子節點和孫節點比較
swap(&arr[dad], &arr[son]);
dad = son;
son = dad * 2 + 1;
}
}
}
void heap_sort(int arr[], int len) {
int i;
// 初始化,i從最後一個父節點開始調整
for (i = len / 2 - 1; i >= 0; i--)
max_heapify(arr, i, len - 1);
// 先將第一個元素和已排好元素前一位做交換,再重新調整,直到排序完畢
for (i = len - 1; i > 0; i--) {
swap(&arr[0], &arr[i]);
max_heapify(arr, 0, i - 1);
}
}
计数排序
以空间换时间的算法,使用该算法的前提条件比较苛刻
- 所有元素是整数
- 元素个数是有限个数
算法逻辑:
- 将所有元素当作一个数组的下标,用以统计每个下标处数据的个数
- 按照数组顺序以及统计个数输出结果
int countSort3(int *A, int len, int *result) {
// 找出数组A中的最大值、最小值
int min = A[0];
int min = A[0];
int i;
int *count;
for (i=1; i<len; i++) {
if(min > A[i])
min = A[i];
if(max < A[i])
max = A[i];
}
// 初始化计数数组count
// 长度为最大值减最小值加1
count = calloc(max-min+1, sizeof(int));
// 对计数数组各元素赋值
for (i=0;i<len;i++) {
// A中的元素要减去最小值,再作为新索引
count[A[i]-min]++;
}
// 计数数组变形,新元素的值是前面元素累加之和的值
for (int i=1; i<=max-min; i++) {
count[i] += count[i-1];
}
// 遍历A中的元素,填充到结果数组中去
for (int j=0; j<len; j++) {
result[count[A[j]-min]-1] = A[j];
count[A[j]-min]--;
}
free(count);
}
桶排序
将待排序数组按照大小进行分组,比如1000个数(1000以内),将其分到10个桶(数组)里面进行排序, 可以采用[0,99],[100,199],[200,299],[300,399],[400,499],[500,599],[600,699],[700,799],[800,899],[900,999]
再对每个区间内数据进行排序。 最后再合并到一起。
//关于分桶这一块暂时想不到如何最好的方式分出合适数量的桶,可以先参考https://blog.csdn.net/developer1024/article/details/79770240
基数排序
也是桶排序的思想
- 对比所有数据个位,进行排序。
- 将上面结果对比所有数据十位,进行排序。
- 将上面结果对比所有数据百位,进行排序。
以此类推
void radixsort(int *a, int n) {
int i, b[MAX], m = a[0], exp = 1;
for (i = 1; i < n; i++) {
if (a[i] > m) {
m = a[i];
}
}
while (m / exp > 0) {
int bucket[BASE] = { 0 };
for (i = 0; i < n; i++) {
bucket[(a[i] / exp) % BASE]++;
}
for (i = 1; i < BASE; i++) {
bucket[i] += bucket[i - 1];
}
for (i = n - 1; i >= 0; i--) {
b[--bucket[(a[i] / exp) % BASE]] = a[i];
}
for (i = 0; i < n; i++) {
a[i] = b[i];
}
exp *= 10;
}
}