桶排序,二分插入排序,基数排序待写。。。
冒泡排序
void sort(int *a, int len)
{
for(int i=0; i<len-1; i++)
{
bool flags = true;
for(int j=0; j<len-i-1; j++)
{
if(a[j] > a[j+1])
{
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
flags = false;
}
}
if(flags)break;
}
}
插入排序
void sort(int *a, int len)
{
for(int i=1; i<len; i++)
{
int t = a[i];
int j;
for(j=i; j>0&&t<a[j-1]; j--)
{
a[j] = a[j-1];
}
a[j] = t;
}
}
希尔排序
void ShellSort(int array[],int length)
{
int d = length/2; //设置希尔排序的增量
int i, j, temp;
while(d>=1)
{
for(i=d; i<length; i++)
{
temp = array[i];
j = i-d;
while(j>=0 && array[j]>temp)
{
array[j+d] = array[j];
j = j-d;
}
array[j+d] = temp;
}
print(array,length);
d= d/2; //缩小增量
}
}
void ShellSort(int *a, int len)
{
for (int d=len/2; d>=1; d/=2)
{
int j, temp;
for (int i=d; i<len; i++)
{
temp = a[i];
j = i - d;
while (j>=0 && a[j]>temp)
{
a[j+d] = a[j];
j -= d;
}
a[j+d] = temp;
}
}
}
选择排序
void sort(int *a, int len)
{
for(int i=0; i<len-1; i++)
{
int min = i;
for(int j=i+1; j<len; j++)
{
if(a[j] < a[min])
min = j;
}
if(min != i)
swap(a[min, a[i]]);
}
}
快速排序
方式一:
方式二(优化后,效率更高):
void sort(int *a, int len)
{
if(len<1) return;
int L = 0;
int R = len-1;
while(L<R)
{
while(L<R&&a[R]>=a[L]) R--;
swap(a[L], a[R]);
while(L<R&&a[R]>=a[L]) L++;
swap(a[L], a[R]);
}
sort(a, L);//左边分组,长度传L和R一样
sort(a+L+1, len-L-1);//右边分组,长度之和为len-1
}
方式二(优化后,效率更高):
void sort(int *a, int len)
{
if(len<1) return;
int L = 0;
int R = len-1;
int piv = a[0];
while(L<R)
{
while(L<R&&a[R]>=piv) R--;
a[L] = a[R];
while(L<R&&a[L]<=piv) L++;
a[R] = a[L];
}
a[L] = piv;//等价于a[R] = piv;
sort(a, L);//左边分组,长度传L和R一样
sort(a+L+1, len-L-1);//右边分组,长度之和为len-1
}
归并排序
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,
取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,
取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
//将有序数组a[]和b[]合并到c[]中
void MemeryArray(int a[], int n, int b[], int m, int c[])
{
int i, j, k;
i = j = k = 0;
while (i < n && j < m)
{
if (a[i] < b[j])
c[k++] = a[i++];
else
c[k++] = b[j++];
}
while (i < n)
c[k++] = a[i++];
while (j < m)
c[k++] = b[j++];
}
可以看出合并有序数列的效率是比较高的,可以达到O(n)。解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,
如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,
然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。
//将有二个有序数列a[first...mid]和a[mid...last]合并。
void mergearray(int a[], int first, int mid, int last, int temp[])
{
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0;
while (i <= m && j <= n)
{
if (a[i] <= a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i <= m)
temp[k++] = a[i++];
while (j <= n)
temp[k++] = a[j++];
for (i = 0; i < k; i++)
a[first + i] = temp[i];
}
void mergesort(int a[], int first, int last, int temp[])
{
if (first < last)
{
int mid = (first + last) / 2;
mergesort(a, first, mid, temp); //左边有序
mergesort(a, mid + 1, last, temp); //右边有序
mergearray(a, first, mid, last, temp); //再将二个有序数列合并
}
}
bool MergeSort(int a[], int n)
{
int *p = new int[n];
if (p == NULL)
return false;
mergesort(a, 0, n - 1, p);
delete[] p;
return true;
}
归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。因为归并排序每次都是在相邻的数据中进行操作,
所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。
在本人电脑上对冒泡排序,直接插入排序,归并排序及直接使用系统的qsort()进行比较(均在Release版本下)
注:有的书上是在mergearray()合并有序数列时分配临时数组,但是过多的new操作会非常费时。
因此作了下小小的变化。只在MergeSort()中new一个临时数组。后面的操作都共用这一个临时数组。
堆排序
方式一:
//堆排序
void heapSort(int *a, int len)
{
//建立大根堆,其实就是调堆的过程(从最后一个非叶子节点开始)
int first = (len-2)/2;
for (int i=first; i>=0; i--)
{
adjustHeap(a, len, i);
}
int temp;
for (int j=len-1; j>=0; j--)
{
temp = a[j];
a[j] = a[0];
a[0] = temp;
adjustHeap(a, j, 0);//调整首元素
}
}
void adjustHeap (int *array, int len, int i)
{
int left = 2*i+1;
int right = 2*i+2;
int largest = i;
if (left < len && array[left] > array[i])
largest = left;
if (right < len && array[right] > array[largest])
largest = right;
int temp;
if (largest != i)
{
temp = array[largest];
array[largest] = array[i];
array[i] = temp;
adjustHeap(array, len, largest);
}
}
方式二:
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int HEAP_SIZE = 13; //堆積樹大小
int parent(int);
int left(int);
int right(int);
void Max_Heapify(int [], int, int);
void Build_Max_Heap(int []);
void print(int []);
void HeapSort(int [], int);
/*父結點*/
int parent(int i)
{
return (int)floor((i - 1) / 2);
}
/*左子結點*/
int left(int i)
{
return (2 * i + 1);
}
/*右子結點*/
int right(int i)
{
return (2 * i + 2);
}
/*單一子結點最大堆積樹調整*/
void Max_Heapify(int A[], int i, int heap_size)
{
int l = left(i);
int r = right(i);
int largest;
int temp;
if(l < heap_size && A[l] > A[i])
{
largest = l;
}
else
{
largest = i;
}
if(r < heap_size && A[r] > A[largest])
{
largest = r;
}
if(largest != i)
{
temp = A[i];
A[i] = A[largest];
A[largest] = temp;
Max_Heapify(A, largest, heap_size);
}
}
/*建立最大堆積樹*/
void Build_Max_Heap(int A[])
{
for(int i = (HEAP_SIZE-2)/2; i >= 0; i--)
{
Max_Heapify(A, i, HEAP_SIZE);
}
}
/*印出樹狀結構*/
void print(int A[])
{
for(int i = 0; i < HEAP_SIZE;i++)
{
printf("%d ", A[i]);
}
printf("\n");
}
/*堆積排序程序碼*/
void HeapSort(int A[], int heap_size)
{
Build_Max_Heap(A);
int temp;
for(int i = heap_size - 1; i >= 0; i--)
{
temp = A[0];
A[0] = A[i];
A[i] = temp;
Max_Heapify(A, 0, i);
}
print(A);
}
/*輸入資料並做堆積排序*/
int main(int argc, char* argv[])
{
int A[HEAP_SIZE] = {19, 1, 10, 14, 16, 4, 7, 9, 3, 2, 8, 5, 11};
HeapSort(A, HEAP_SIZE);
system("pause");
return 0;
}