排序

来源:互联网 发布:linux 开启snmp 编辑:程序博客网 时间:2024/05/19 16:04

排序(sorting):将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列。排序分内部排序和外部排序。
外部排序:指的是待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过尚需对外存进行访问的排序过程。
内部排序:指的是待排序记录存放在计算机随机存储器中进行的排序过程。
依据不同原则对内部排序方法进行分类:交换排序、插入排序、选择排序、归并排序、基数排序。通常,在排序过程中需进行两种基本操作:(1)比较两个关键字的大小;(2)将记录从一个位置移动另一个位置。前一个操作对大多数排序方法都是不要的,而后一个操作可以通过改变记录的存储方式以避免;3种存储方式:1)待排序的一组记录存放在地址连续的一组存储单元上;必须借助移动记录来实现。2)一组待排序记录存放在静态链表中;不需要移动记录,仅需修改指针即可(又称表排序)。3)待排序记录本身存储在一组连续的存储单元内,同时另设一个指示各个记录的存储位置的地址向量;不需要移动记录本身,需移动地址向量中这些记录的地址(又称地址排序)。
:排序稳定性:待排序记录记录中,存在两个或两个以上的记录具有相同的关键字,在用某种排序法排序后,若这些相同关键字的元素的相对次序仍然不变,则这种排序方法是稳定的;反之这种排序方法是不稳定的。(1)交换排序:根据序列中两个键值的比较结果来对换两个记录在序列中的位置;特点:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。冒泡排序(bubble sort):第i趟冒泡排序是从a[0]到a[n-i]依次比较相邻两个记录的关键字,并在逆序时交换相邻记录(可以用一趟排序过程中没有进行交换记录的操作作为结束条件)。快速排序(quick sort):是对冒泡排序的一种改进。通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。一趟快速排序的步骤:附设两个指针low和high,设枢轴记录的关键字为pivotKey;则首先从high所指位置起向前搜索找到第一个关键字小于pivotKey的记录和枢轴记录交换;然后从low所指位置起向后搜索找到第一个关键字大于pivotKey的记录和枢轴记录交换;重复这两步直至low=high(在排序过程中对枢轴位置的赋值是多余的,因为只有在一趟排序结束时即low=high的位置才是枢轴的最后位置)。(2)插入排序(insert sort):将有序记录从后向前扫描找到合适的位置插入未排序记录,对未排序记录从前向后扫描直至所有的记录都被排序。直接插入排序(straight insert sort):将一个记录插入到已经排好的有序表中,从而得到一个新的、记录数增加1的有序表。第i(i>=2)趟直接插入排序:在含有i-1个记录有序子序列中a[i-2]中插入一个记录a[i-1];后变为含有i个记录的有序子序列a[i-1];在自i-2起向前搜索过程中,可以同时向后移动记录;整个排序过程进行n-1趟插入。希尔排序(shell’s sort):又称缩小增量排序,是对直接插入排序的一种改进;先将整个待排序记录分割成为若干子序列分别进行直接插入排序(一趟希尔排序),待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。特点:子序列的构成不是简单的“逐段分割”而是将相隔某个“增量”的记录组成一个子序列。(3)选择排序(selection sort):每一趟在n-i+1(i=1,2, … ,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。简单选择排序(simple selection sort):第i趟简单选择排序,通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i个记录交换之。堆排序(heap sort):n个元素的序列{k1,k2, … ,kn}当且仅当满足下列关系称为堆。Ki<=k2i且ki<=k2i+1;或Ki>=k2i且ki>=k2i+1(i=1,2,… ,[n/2]);若在输出堆顶的最小值后,使得剩余n-1个元素的序列重建成一个堆,则得到n个元素的次小值,反复执行便能得到一个有序序列,这个过程称之为堆排序。(4)归并排序(merging sort):初始数列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并,… ,如此重复直至得到一个长度为n的有序序列为止,这种排序方法称为2-路归并排序。整个归并操作需要进行[log2n]趟。(5)基数排序(radix sort):不需要进行记录关键字间的比较。是一种借助多关键字排序的思想对单逻辑关键字进行排序的方法。

排序方法 时间复杂度 空间复杂度 稳定性 交换排序 冒泡排序 O(n^2) O(1) 稳定 快速排序 O(nlogn) O(nlogn) 不稳定 选择排序 简单选择排序 O(n^2) O(1) 不稳定 堆排序 O(nlogn) O(1) 不稳定 归并排序 O(nlogn) O(n) 稳定 基数排序 O(d*n) O(d*n) 稳定


//bubbleSortvoid bubbleSort(int a[], int n){    int temp;    for (int i = 0; i < n - 1;i++){        //第i趟冒泡排序是从a[0]到a[n-i]依次比较相邻两个记录的关键字        for (int j = 0; j < n - i - 1; j++){              if (a[j] > a[j + 1]){                temp = a[j];                a[j] = a[j+1];                a[j + 1] = temp;            }        }    }}//partition:一趟快速排序int partition(int a[],int low,int high){    int pivotKey = a[low]; //枢轴记录的关键字    while (low<high){        while (low < high&&a[high] >= pivotKey)            high--;         a[low] = a[high]; //将比枢轴小的交换到低端        while (low < high&&a[low] <= pivotKey)            low++;        a[high] = a[low]; //将比枢轴大的交换到高端    }    a[low] = pivotKey; //一趟排序结束,将枢轴记录到相应的位置low    return low; //返回枢轴所在的位置}//quickSort:快速排序的递归实现void quickSort(int a[],int low,int high){    if (low<high){ //长度大于1        int pivotLoc = partition(a,low,high); //将data表一分为二,pivotLoc是枢轴位置        quickSort(a, low, pivotLoc - 1); //对低子表递归排序        quickSort(a, pivotLoc+1, high); //对高子表递归排序    }}//straight insertion sort:直接插入排序void insertSort(int a[], int n){    int x; //哨兵    for (int i = 1; i < n; i++){ //n-1趟插入        if (a[i] < a[i - 1]){            x = a[i]; //复制为哨兵            int j; //待插入的位置            for (j = i - 1; x < a[j]; j--) //确定带插入位置j,并将记录后移                a[j + 1] = a[j];            a[j + 1] = x; //插入到正确位置        }    }}//shell sort:为一趟希尔排序;重复多次直至dk为1希尔排序结束void shellSort(int a[],int n,int dk){    //dk是前后记录的增量,而不是1    int x;    for (int i = dk; i < n;i++){        if (a[dk] < a[i - dk]){            x = a[i];            int j;            for (j = i - dk; j >= 0 && x < a[j]; j -= dk)                a[j + dk] = a[j];            a[j + dk] = x;        }    }}//simple selection sort:简单选择排序void selectSort(int a[],int n){    int index; //每一趟选择排序的最小值的索引    int min; //每一趟选择排序的最小值    for (int i = 0; i < n - 1; i++){        index = i;        for (int j = i + 1; j < n; j++)            if (a[index] > a[j])                index = j;        min = a[index];        a[index] = a[i];        a[i] = min;    }}//merging sort:归并排序;一趟归并操作需要调用[n/2h]次算法merge,h为子序列长度void merge(int a[],int b[],int i,int m,int n){    //将有序的a[i, ... ,m]和a[m+1, ... ,n]归并为有序的b[i, ... ,n]    int j; //有序的a[m+1, ... ,n]的索引    int k; //b[i, ... ,n]的索引    for (j = m + 1, k = i; i <= m&&j <= n;k++){ //将a中的记录由小到大并入b中        if (a[i] < a[j])            b[k] = a[i++];        else            b[k] = a[j++];    }    while (i <= m) //将剩余的a[i, ... ,m]复制到b中        b[k++] = a[i++];    while (j <= n) //将剩余的a[j, ... ,n]复制到b中        b[k++] = a[j++];}void mergeSort(int a[],int b[],int s,int t){    //将a[s, ... ,t]归并排序为b[s, ... ,t]    int* b1;    if (s == t)        b[s] = a[s];    else{        int m = (s + t) / 2;        mergeSort(a,b1,s,m);        mergeSort(a,b1,m+1,t);        merge(b1,b,s,m,t);    }}
0 0
原创粉丝点击