1.常见算法分类
十种常见排序算法一般分为以下几种:
(1)非线性时间比较类排序:交换类排序(快速排序和冒泡排序)、插入类排序(简单插入排序和希尔排序)、选择类排序(简单选择排序和堆排序)、归并排序(二路归并排序和多路归并排序);
(2)线性时间非比较类排序:计数排序、基数排序和桶排序。
总结:
(1)在比较类排序中,归并排序号称最快,其次是快速排序和堆排序,两者不相伯仲,但是有一点需要注意,数据初始排序状态对堆排序不会产生太大的影响,而快速排序却恰恰相反。
(2)线性时间非比较类排序一般要优于非线性时间比较类排序,但前者对待排序元素的要求较为严格,比如计数排序要求待排序数的最大值不能太大,桶排序要求元素按照hash分桶后桶内元素的数量要均匀。线性时间非比较类排序的典型特点是以空间换时间。
注:本博文的示例代码均已递增排序为目的。
2.1交换类排序
2.1.1冒泡类排序
void BubbleSort(int *arr,int size)
{
int i,j;
int flag,tmp;
for(i = 0 ;i < size; i++)
{
flag = 1;
for(j = 0 ; j < size - i - 1;j++)
{
if(arr[j] > arr[j + 1])
{
flag = 0;
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
if(1 == flag)
{
break;
}
}
}
2.1.2快速排序
int Departition(int *arr,int left ,int right)
{
int tmp = arr[left];
while(left < right)
{
while(left < right && tmp < arr[right])
right--;
if(left < right)
arr[left++] = arr[right];
while(left < right && tmp > arr[left])
left++;
if(left < right)
arr[right--] = arr[left];
}
arr[left] = tmp;
return left;
}
void DoQuickSort(int *arr,int left,int right)
{
int t;
if(left < right)
{
t = Departition(arr,left,right);
DoQuickSort(arr,0,t - 1);
DoQuickSort(arr,t + 1,right);
}
}
void QuickSort(int *arr,int size)
{
DoQuickSort(arr,0,size -1);
}
2.2 插入类排序
2.2.1直接插入
void InsertSort(int *arr,int size)
{
int i,j,tmp;
for(i = 1 ; i < size; i++)
{
tmp = arr[i];
j = i;
while(j >= 1 && tmp < arr[j -1])
{
arr[j] = arr[j -1];
j--;
}
arr[j] = tmp;
}
}
2.2.2 shell排序
void ShellSort(int *arr,int size,int d)
{
int i,j,k,tmp;
for(i = d;i > 0;i = i/2)
{
for(j = 0 ;j < size ; j += i)
{
tmp = arr[j];
k = j;
while(k >= i && tmp < arr[k - i])
{
arr[k] = arr[k - i];
k -= i;
}
arr[k] = tmp;
}
}
}
2.3选择类排序
2.3.1直接选择类排序
void SelectSort(int *arr,int size)
{
int i,j,min;
int tmp;
for(i = 0 ;i < size; i++)
{
min = i;
for(j = i + 1; j < size ; j++)
{
if(arr[min] > arr[j])
min = j;
}
if(i != min)
{
tmp = arr[i];
arr[i] = arr[min];
arr[min] = tmp;
}
}
}
2.3.2 堆排序
void AdjustHeap(int *arr,int node,int size)
{
int child = 2*node + 1;
int tmp = arr[node];
while(child < size)
{
if(child + 1 < size && arr[child] < arr[child + 1])
{
child++;
}
if(tmp < arr[child])
{
arr[node] = arr[child];
node = child;
arr[node] = tmp;
child = 2*child + 1;
}
else
{
break;
}
}
}
void HeapSort(int *arr,int size)
{
int i,j,tmp;
for(i = (size -1)/2 ; i >= 0 ; i--)
AdjustHeap(arr,i,size);
/* printf("after create heap\n");
for(i = 0 ; i < MAX ; i++)
{
printf("%d ",arr[i]);
}
printf("\n");
*/
for(i = 1 ;i < size; i++)
{
tmp = arr[0];
arr[0] = arr[size - i];
arr[size - i] = tmp;
AdjustHeap(arr,0,size -i);
}
}
2.4归并排序
void Merge(int *src,int *tmp,int begin,int mid,int end)
{
int i = begin ,j = mid + 1,k = begin;
while( i != mid + 1 && j != end + 1)
{
if(src[i] > src[j])
{
tmp[k++] = src[j++];
}
else
{
tmp[k++] = src[i++];
}
}
while(i != mid + 1)
{
tmp[k++] = src[i++];
}
while(j != end + 1)
{
tmp[k++] = src[j++];
}
for(i = begin ; i <= end; i++)
{
src[i] = tmp[i];
}
}
void MergeSort(int *src,int *tmp,int begin,int end)
{
int mid;
if(begin < end)
{
mid = (begin + end)/2;
MergeSort(src,tmp,begin,mid);
MergeSort(src,tmp,mid+1,end);
Merge(src,tmp,begin,mid,end);
}
}
以上是非线性时间比较类排序, 线性时间非比较类排序常见方法如下。
2.5计数排序
void CountSort(int *arr,int size)
{
int i,j,count,max;
int *tmp;
max = arr[0];
for(i = 1;i < size; i++)
{
if(max < arr[i])
{
max = arr[i];
}
}
tmp = (int *)malloc(sizeof(int)*(max + 1));
if(NULL == tmp)
{
printf("malloc failure\n");
return;
}
memset(tmp,0,sizeof(int)*(max + 1));
for(i = 0 ; i < size ; i++)
{
tmp[arr[i]]++;
}
count = 0;
for(i = 0;i <= max; i++)
{
j = 0;
while(j < tmp[i])
{
arr[count++] = i;
j++;
}
}
free(tmp);
tmp = NULL;
}
2.6 基数排序
int GetDigitalPos(int num,int pos)
{
int i,mask = 1;
for(i = 0;i < pos -1; i++)
{
mask *= 10;
}
return (num/mask)%10;
}
void DistributionSort(int *arr,int size)
{
int *buff[10] = {NULL}; /* 0 ~ 9 */
int i,j;
for(i = 0 ;i < 10; i++)
{
buff[i] = (int *)malloc(sizeof(int)*(size + 1));
if(NULL == buff[i])
{
for(j = 0; j < i; j++)
{
free(buff[j]);
buff[j] = NULL;
return;
}
}
buff[i][0] = 0; /* 保存统计数目 */
}
int index,count,k;
for(i = 1; i < MAX_BIT; i++)
{
/* 装入桶中 */
for(j = 0; j < size; j++)
{
index = GetDigitalPos(arr[j],i);
buff[index][buff[index][0]+1] = arr[j];
buff[index][0]++;
}
/* 将桶中数据装回原空间 */
count = 0;
for(j = 0; j < 10; j++)
{
for(k = 0; k < buff[j][0]; k++)
{
arr[count++] = buff[j][k + 1];
}
buff[j][0] = 0;
}
}
/* 释放桶空间 */
for(i = 0 ;i < 10; i++)
{
free(buff[i]);
buff[i] = NULL;
}
}
2.7 桶排序
struct bucket
{
int num;
int val;
struct bucket *next;
};
void Release(struct bucket **root,int num)
{
int i;
struct bucket *node,*next;
struct bucket **tmp = root;
if(NULL == tmp)
{
return;
}
for(i = 0; i < num; i++)
{
if(tmp[i])
{
node = tmp[i];
while(node)
{
next = node ->next;
free(node);
node = next;
}
tmp[i] = NULL;
}
}
if(tmp)
{
free(tmp);
tmp = NULL;
}
}
void BucketSort(int *arr,int size)
{
int i,index;
struct bucket *p,*node;
struct bucket **root = (struct bucket **)malloc(sizeof( struct bucket *)*BUCKET_NUM);
if(NULL == root)
{
printf("malloc failure \n");
return;
}
for(i = 0; i < BUCKET_NUM; i++)/* BUCKET_NUM 桶数目 */
{
root[i] = (struct bucket *)malloc(sizeof(struct bucket));
if(NULL == root[i])
{
Release(root,BUCKET_NUM);
return;
}
root[i] ->num = 0;
root[i] ->next = NULL;
root[i] ->val = 0;
}
/* 将数据装入桶中 */
for(i = 0; i < size; i++)
{
index = arr[i]/BUCKET_NUM;
p = root[index];
node = (struct bucket *)malloc(sizeof(struct bucket));
if(NULL == node)
{
Release(root,BUCKET_NUM);
return;
}
node ->val = arr[i];
node ->next = NULL;
if(p ->num == 0)
{
p ->next = node;
}
else
{
while(p ->next && p ->next ->val <= arr[i])
p = p ->next;
node ->next = p ->next;
p ->next = node;
}
(p ->num)++;
}
/* 打印 */
for(i = 0; i < BUCKET_NUM; i++)
{
p = root[i] ->next;
while(p != NULL)
{
printf("%d ",p ->val);
p = p ->next;
}
}
printf("\n");
Release(root,BUCKET_NUM);
}
转:https://blog.youkuaiyun.com/coolwriter/article/details/78732728