排序 c++

来源:互联网 发布:数据建模 编辑:程序博客网 时间:2024/05/04 06:20

下列是十种排序的实现:

1.插入排序

void InsertSort(int a[], int n){ int i, j;for (i = 1; i < n; ++i){int t = a[i];//暂存待插码for (j = i - 1; t < a[j] && j >= 0; --j)//寻找插入位置a[j + 1] = a[j];//后移a[j + 1] = t;}}

2.希尔排序

在插入排序基础上改进,将整个排序的序列分割为若干子序列,子序列内部排序插入排序,待整个序列基本有序时对全体插入排序。
使用的分割方法是取d<n,所有相距为d的码构成一个子序列,插入排序,然后缩小d再进行排序,直到d=1,再将全体进行插入排序。可以令d=n/2,然后每次缩小d时,令d=d/2。

void ShellSort(int a[], int n){int d, i, j;for (d = n / 2; d >= 1; d = d / 2){for (i = d + 1; i <= n; ++i){a[0] = a[i];for (j = i - d; a[0] < a[j]; j -= d)a[j + d] = a[j];a[j + d] = a[0];}}}

3.冒泡排序

void BubbleSort(int a[], int n){int i, j;for (i = 0; i < n; ++i)for (j = 0; j < n - i-1;++j)if (a[j]>a[j+1]){int t=a[j];a[j] = a[j+1];a[j+1] = t;}}

4.快速排序

以一个码为轴,将序列化为两部分,左边小于等于轴值,右边大于等于轴值,重复操作直到序列有序。
下面代码用的选取轴值策略是取待划分部分的末尾为轴,小于等于它的元素则按左到右的顺序依次与其左侧元素交换,最后再将轴值交换到最后一次交换位置的下一位置。
而取轴值位置将关系到算法的性能

int Partition(int a[], int p, int r)//取轴值并交换{int i = p - 1, j;for (j = p; j < r;++j)if (a[j]<=a[r]){++i;int t = a[i];a[i] = a[j];a[j] = t;}int t = a[i + 1];a[i + 1] = a[r];a[r] = t;return i + 1;}void QuickSort(int a[], int p, int r)//初始QuickSort(a, 0, n-1){if (p < r){int q = Partition(a,p,r);QuickSort(a,p,q-1);QuickSort(a,q+1,r);}}

5.选择排序

void SelectSort(int a[], int n){int i, j, k;for (i = 0; i < n-1; ++i){k = i;for (j = i+1; j < n; ++j)if (a[j] < a[k])k = j;if (k != i){int t = a[j];a[j] = a[i];a[i] = t;}}}

6.堆排序

堆为一棵完全二叉树,子女比自己小者为最大堆,子女比自己大者为最小堆。因此,最大堆
的根结点为最大元素,最小堆的根结点为最小元素,堆排序就是利用这一点,每次将堆的根
结点移除,重新调整堆,如此重复直到堆为空,这样堆中元素即按从大到小从堆中取出。

#define PARENT(i) i/2//当前结点父结点下标#define LEFT(i) 2*i//当前结点左孩子下标#define RIGHT(i) (2*i+1)//当前结点右孩子下标void MaxHeapify(int a[], int k, int i)//保持最大堆性质,k是堆的长度,a下标要从1开始{int l=LEFT(i), r=RIGHT(i);int largest=0;if (l <= k&&a[l] > a[i])largest = l;elselargest = i;if (r <= k&&a[r] > a[largest])largest = r;if (largest != i){int t = a[i];a[i] = a[largest];a[largest] = t;MaxHeapify(a, k, largest);}}void BuildMaxHeap(int a[],int n)//初始化最大堆{for (int i = n / 2; i > 0; --i)MaxHeapify(a, n, i);}void HeapSort(int a[], int n)//堆排序,a[0]作为交换中间量{BuildMaxHeap(a, n);int k = n;for (int i = n ; i >= 2; --i){a[0] = a[1];a[1] = a[i];a[i] = a[0];--k;MaxHeapify(a, k, 1);}}

7.归并排序

将两堆已排好序的元素合并,合并过程就是一一比较两个序列中的元素,按大小顺序重新排
成一个序列,因为两个序列均为已排好序的序列,所以合并两个总长为n的序列的过程只耗
费O(n),然后重复合并过程,直到整个序列有序。

void Merge(int a[], int x, int y, int z)//合并a[p...q]与a[q+1...r],假设其已经排好序{int n1 = x - y + 1, n2 = z - y;int *l = new int[n1];int *r = new int[n2];for (int i = 0; i < n1; ++i)l[i] = a[x + i];for (int i = 0; i < n2; ++i)r[i] = a[y + i + 1];l[n1] = INF;//设置哨兵r[n2] = INF;int i = 0, j = 0;for (int k = x; k <= z; ++k){if (l[i] < r[j]){a[k] = l[i];++i;}else{a[k] = r[j];++j;}}}void MergeSort(int a[], int x, int z)//初始参数MergeSort(a, 0, n){if (x < z){int y = (x + z) / 2;MergeSort(a, x, y);MergeSort(a, y, z);Merge(a, x, y, z);}}

8.计数排序

计数排序假设n个输入元素中的每一个均是0到k之间的数,k某整数,用一中间暂存数组存储
每个数的个数(即用每个待排数作为数组下标)来作为该数在结果数组中的位置依据,这样
序列中重合的元素也能得到很好的处理。计数排序因为并没有用比较的方法排序,所有计数
排序下界优于基于比较的排序下界O(nlogn),但要使用大量额外的空间去暂存中间数据。

void CountSort(int a[], int b[], int n, int k)//a[]为待排序列,b[]存储结果{int *c = new int[k+1];for (int i = 0; i <= k; ++i)//初始化暂存每个数个数的数组,下标为序列中的数。c[i] = 0;for (int i = 0; i < n; ++i)//每个单元存储的内容为该数个数。++c[a[i]];for (int i = 1; i <= k; ++i)//每个单元存储小于或等于该数的元素个数,以此作为该数在序列中的位置c[i] += c[i - 1];for (int i = n - 1; i >= 0; --i){b[c[a[i]]] = a[i];--c[a[i]];}}

9.基数排序

基数排序利了多个关键码排序的思想对单关键码排序,将单关键码按位排序,按位排序可使
用任意排序方法,与直觉相反的是基数排序是按从低位到高位的次序排序,这样避免了从高
位到低位排序时产生的中间状态不参与排序的数,n个k进制d位数,若使用计数排序,则时间
复杂度为O(d(n+k))

void CountSort(int a[], int b[], int n, int k,int d)//用于基数排序,按a[]的第d位排序{int *c = new int[k+1];for (int i = 0; i <= k; ++i)c[i] = 0;for (int i = 0; i < n; ++i){int t=a[i];int temp = 1;for (int j = 0; j < d; ++j)temp *= 10;t = (t / temp)%10;++c[t];}for (int i = 1; i <= k; ++i)c[i] += c[i - 1];for (int i = n - 1; i >= 0; --i){int t = a[i];int temp = 1;for (int j = 0; j < d; ++j)temp *= 10;t = (t / temp) % 10;b[c[t]] = a[i];--c[t];}}void RadixSort(int a[], int n, int d){int *b = new int[n];for (int i = 0; i < d; ++i){//用一种稳定算法对序列按第d位排序,可以使用计数排序CountSort(a, b, n, 9, d);//对十进制序列按第d位计数排序for (int i = 0; i < n; ++i)a[i] = b[i];}}

10.桶排序

桶排序的思想就是将序列元素的区间划为x等分,每一等分即为一个桶,对每个桶中的元素进
行排序,一般用链表,所以用插入排序,最后把所有元素从桶中取出即排好序。桶排序需要用
到额外存放链表(即桶)的数组,并且假设序列是均匀分布的,所有,输入序列趋于均匀分
布时,桶排序趋于线性期望时间

0 0