排序的概念:
1.排序就是将一组没有规律的数据按照一定的规律进行(升序/降序)排序。
2.一个元素数列如果两个元素A,B。如果在排序之前A在B的前面,在排序之后A依然在B的前面。那么我们就说这个排序算法是稳定的。
常见的排序算法:
1.插入排序:
《1》直接插入排序:
直接插入代码如下:
void Insertsort(int arry[],int size)
{
int key;
int i, j;
for (i = 1; i < size; i++)
{
key = arry[i];
for (j = i - 1; j >= 0; j--)
{
if(key>=arry[j])
{
break;
}
else
{
arry[j + 1] = arry[j];
}
}
arry[j + 1] = key;
}
}
《2》希尔排序:
希尔排序代码如下:
void elseInsertsort(int array[], int size, int gap)
{
int key;
int i, j;
for (i = gap; i < size; i++) {
key = array[i];
for (j = i - gap; j >= 0; j -= gap) {
if (key >= array[j]) {
break;
}
else {
array[j + gap] = array[j];
}
}
array[j + gap] = key;
}
}
void Shellsort(int arry[],int size)
{
int gap = size;
while (1)
{
gap = gap / 3 +1;
elseInsertsort(arry, size, gap);
if (gap == 1)
{
break;
}
}
}
2.选择排序:
《1》.直接选择排序
直接选择排序代码《1》
如下:
void Directsort(int array[], int size)
{
int i, j;
for(i=size;i>0;i--)
{
int max = 0;
for (j = 0; j < i; j++)
{
if (array[j] > array[max])
max = j;
}
swap(array + max, array + i-1);
}
}
为了使每一次的循环效率更高,我们可以在每一次循环同时找到最小值和最大值,则直接排序的优化版本如下:
void Directsort1(int array[], int size)
{
int left = 0;
int right = size-1;
while (left < right)
{
int j;
int min = left;
int max = left;
for (j = left + 1; j <= right; j++)
{
if (array[j] > array[max])
{
max = j;
}
if (array[j] < array[min])
{
min = j;
}
}
swap(array + left, array + min);
if(max==left)
{
max=min;
}
swap(array + right, array + max);
left++;
right--;
}
}
《2》堆排序
堆排序排序代码如下:
void AdjustDown(int array[], int size, int root)
{
int left = root * 2 +1;
int right = root * 2 +2;
if (left >= size)
{
return;//左孩子超出数组了,跳出
}
int max = left;
if (right<size&&array[right]>array[left])
{
max = right;
}
if (array[root] >= array[max])
{
return;
}
swap(array + root, array + max);
AdjustDown(array, size, max);
}
void CreatHeap(int array[], int size)
{
int i;
for (i = size / 2 - 1; i >= 0; i--)
{
AdjustDown(array, size, i);
}
}
void Heapsort(int array[], int size)
{
CreatHeap(array, size);//创建大堆
int i;
for (i = 0; i < size; i++)
{
swap(&array[0], &array[size - 1 - i]);
AdjustDown(array, size - i - 1, 0);
}
}
3.交换排序
1》冒泡排序
冒泡代码如下:
void Bubbsort(int array[],int size)
{
int i;
int j;
for ( i = 0; i < size - 1; i++)
{
int cur = 1;//用来记录是否已经有序,若已经有序,则直接跳出
for (j = 0; j < size - 1 - i; j++)
{
if (array[j] > array[j + 1])
{
swap(array + j, array + j + 1);
cur = 0;
}
}
if (cur == 1) {
break;
}
}
}
2》快速排序
快速排序代码如下:
int seachdel3(int array[], int left, int right)
{
int cur, div;
for (cur = left, div = left; cur < right; cur++)
{
if (array[cur] < array[right])
{
Swap(array + cur, array + div);
div++;
}
}
Swap(array + div, array + right);
return div;
}
int seachdel2(int array[], int left, int right)
{
int begin = left;
int end = right;
int pivot = array[right];
while (begin < end)
{
while (begin < end && array[begin] <= pivot)
{
begin++;
}
array[end] = array[begin];
while (begin < end && array[end] >= pivot)
{
end--;
}
array[begin] = array[end];
}
array[begin] = pivot;
return begin;
}
int seachdel1(int array[],int left,int right)
{
int begin = left;
int end = right;
int del = array[right];
while (begin < end)
{
while (begin < end && array[begin] <= del) {
begin++;
}
array[end] = array[begin];
while (begin < end && array[end] >= del) {
end--;
}
array[begin] = array[end];
}
array[begin] = del;
return begin;
}
void _quicksort(int array[], int left, int right)
{
if (left >= right)
{
return;
}
int del = seachdel1(array, left, right);
_quicksort(array, left, del-1);
_quicksort(array, del + 1, right);
}
void Quicksort(int array[],int size)
{
_quicksort(array, 0, size - 1);
}
归并排序:
归并排序代码如下:
void merge(int array[], int left, int mid, int right, int extra[])
{
int left_i=left;//左区间第一个下标
int right_i = mid;//右区间第一个下标
int extra_i = left;//临时储存第一个下标
while (left_i < mid && right_i < right) {
if (array[left_i] <= array[right_i]) {
extra[extra_i++] = array[left_i++];
}
else {
extra[extra_i++] = array[right_i++];
}
}
while (left_i < mid)
{
extra[extra_i++] = array[left_i++];
}
while (right_i < right)
{
extra[extra_i++] = array[right_i++];
}
for (int i = left; i < right; i++)
{
array[i] = extra[i];
}
}
void _Mergesort(int array[],int left,int right,int extra[])
{
if (left >= right)
{
return;//区间内没有元素
}
if (left == right - 1)
{
return;//区间剩一个元素了,不用在排序了
}
int mid = left + (right - left )/ 2;
_Mergesort(array, left, mid, extra);
_Mergesort(array, mid, right, extra);
merge(array, left, mid, right, extra);
}
void Mergesort(int array[], int size)
{
int *extra = (int *)malloc(sizeof(int)*size);//申请的空间
_Mergesort(array, 0, size, extra);
free(extra);
}
void Mergesort2(int array[],int size)
{
int i;
int j;
int *extra = (int *)malloc(sizeof(int)*size);
for (i = 1; i < size; i *= 2)
{
for (j = 1; j < size; j = j + i * 2)
{
int left = i;
int mid = i + j;
int right = mid + i;
if (mid >= size)
{
continue;
}
if (right > size)
{
right = size;
}
merge(array, left, mid, right, extra);
}
}
free(extra);
}
总结如下:
(1)若n较小,可采用直接插入或直接选择排序。
(2)若文件初始状态基本有序,则应选用直接插人、冒泡或随机的快速排序。
(3)若n较大,则应采用排序方法:快速排序。
快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短。
复杂度和稳定性如下: