几种常用排序(归并,希尔,快排,堆排.......)
冒泡排序:
最简单的一种排序,重复的遍历数列,每次比较两个元素,按一定的顺序排列;
for(int i=0;i<ength;i++)//length是数组的长度 { for(int j=0;j<length-1-i;j++) { if(a[j]>a[j+1]) swap(a[j],a[j+1]); } }
选择排序:
在未排序的序列中寻找最大(小)元素,存放在起始位置,在剩下未排序的再寻找最大(小)的,直到所有元素排序完成;
for(int i=0;i<10;i++) { int max=i; for(int j=i+1;j<10;j++) { if(a[max]<a[j]) max=j; } swap(a[max],a[i]); }
插入排序:
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面)。
for(int i=1;i<10;i++)//下标元素从1开始,因为下标为0的只有一个元素,默认有序 { int tmp =a[i];//待插入的数 int j=i; while(j>0&&tmp<a[j-1])//遍历是否存在满足条件的数 { a[j]=a[j-1]; j--; } if(j!=i)//存在,插入 a[j]=tmp; }
希尔排序:
选择一个增量序列 t1,t2,……,tk,其中 t1 > t2, tk = 1;
每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
void shell(int arr[],int len) { if(arr==NULL||len==1) return; int div=len/2; while(div) { for(int i=0;i<div;i++) { for(int j=i;j<len-div;j=j+div) { for(int k=j;k<len;k=k+div) if(arr[k]>arr[j]) swap(arr[k],arr[j]); } } div=div/2; } }
int shellSort(int arr[], int len) { int gap = len / 2; while (gap > 0) {// 分组直接插入排序 for (int i = 0; i < len - gap; i++) { int j = i + gap; int tmp = arr[j]; while (j >= gap && tmp < arr[j - gap]) { arr[j] = arr[j - gap]; j -= gap; } arr[j] = tmp; } gap/=2; } return 0; }
归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
void Merge(int a[], int left, int mid, int right) { int len = right - left + 1; // 数组的长度 int *temp = new int[len]; int k = 0; int i = left; int j = mid + 1; while (i <= mid && j <= right) { temp[k++] = a[i] <= a[j] ? a[i++] : a[j++]; } while (i <= mid) { temp[k++] = a[i++]; } while (j <= right) { temp[k++] = a[j++]; } for (int k = 0; k < len; k++) { a[left++] = temp[k]; } } // 递归实现的归并排序 void MergeSort(int a[], int left, int right) { if (left == right) return; int mid = (left + right) / 2; MergeSort(a, left, mid); MergeSort(a, mid + 1, right); Merge(a, left, mid, right); }
快速排序:
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
void Qsort(int a[], int low, int high) { if(low >= high) { return; } int first = low; int last = high; int key = a[first];/*用字表的第一个记录作为枢轴*/ while(first < last) { while(first < last && a[last] >= key) { --last; } a[first] = a[last];/*将比第一个小的移到低端*/ while(first < last && a[first] <= key) { ++first; } a[last] = a[first]; /*将比第一个大的移到高端*/ } a[first] = key;/*枢轴记录到位*/ Qsort(a, low, first-1); Qsort(a, first+1, high); }
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
void PercDown(int A[], int i, int N) { int child; ElementType Tmp; for (Tmp = A[i]; 2*i+1 < N; i = child){ child = 2*i+1; //注意数组下标是从0开始的,所以左孩子的求发不是2*i if (child != N - 1 && A[child + 1] > A[child]) ++child; //找到最大的儿子节点 if (Tmp < A[child]) A[i] = A[child]; else break; } A[i] = Tmp; } void HeapSort(int A[], int N) { int i; for (i = N / 2; i >= 0; --i) PercDown(A, i, N); //构造堆 for(i=N-1;i>0;--i) { Swap(&A[0],&A[i]);//将最大元素(根)与数组末尾元素交换,从而删除最大元素,重新构造堆 PercDown(A, 0, i); } }