- 冒泡排序
重复的走访过要排序的数列。一次比较两个元素,如果他们的顺序错误,就把他们交换过来。走访数列的工作是重复的进行,直到没有再需要交换的元素,即该序列已经排序完成。
void Swap(int* a,int* b){ int tmp = *a; *a = *b; *b = tmp; } void BubbleSort(int arr[],size_t size){ if(size <= 1) return; size_t bound = 0;//[0,bound)表示有序元素,[bound,size)表示待排序元素 for(;bound < size;bound++){ size_t cur = size-1; for(;cur > bound;cur--){ if(arr[cur] < arr[cur-1]) Swap(&arr[cur],&arr[cur-1]); } } return; }
- 选择排序
每一趟从待排序的数据元素中选出最大或最小的一个元素,顺序放在已经排好序的数列的最后,直到全部待排序的数据元素排完。
void Swap(int* a,int* b){ int tmp = *a; *a = *b; *b = tmp; } void SelectSort(int arr[],size_t size){ if(size <= 1) return; size_t bound = 0; for(;bound < size;bound++){ size_t cur = bound+1; for(;cur < size;cur++){ if(arr[bound] > arr[cur]) Swap(&arr[bound],&arr[cur]); } } return; }
- 插入排序
有一个已经有序的数据序列,在这个已经排好序的数据序列中插入一个数,要求插入此数后,该数据序列仍然有序。
void InsertSort(int arr[],size_t size){ if(size <= 1) return; size_t bound = 1; //[0,bound)表示有序元素,[bound,size)表示待排序元素 //插入排序将前面的有序区间当成一个线性表,然后将bound位置的元素插入到线性表中的合适位置 for(;bound < size;bound++){ int bound_value = arr[bound]; size_t cur = bound; for(;cur > 0;cur--){ if(arr[cur-1] > bound_value)//进行搬运 arr[cur] = arr[cur-1]; else//说明已找到合适的位置 break; } arr[cur] = bound_value; } }
- 堆排序
利用堆这种数据结构所设计的一种排序算法,是选择排序的一种。
堆是具有以下性质的完全二叉树:每个节点的值均大于等于其左右孩子结点的值,称为大堆;每个节点的值均小于等于其左右孩子结点的值,称为小堆。
在数组的升序排序中,需要使用的是大堆;在数组的降序排序中,需要使用的是小堆。
堆排序的基本思想是:将待排序序列构成一个大堆(假设升序排序),此时整个序列中的最大值即为堆顶元素的值。将堆顶元素的值与末尾元素的值进行交换,此时末尾元素的值即为最大值。然后将剩余的n-1个元素重新构造成一个堆,这样就会得到n个元素的次小值。如此反复执行,即可得到一个有序序列了。
void AdjustDown(int arr[],size_t size,size_t index){ size_t parent = index; size_t child = 2*parent+1; while(child < size){//升序排序,建立大堆 if(child+1 < size && arr[child+1] > arr[child]) child += 1;//child指向了左右子树中较大的 if(arr[parent] < arr[child]) Swap(&arr[parent],&arr[child]); parent = child; child = 2*parent+1; } return; } void HeapCreate(int arr[],size_t size){ if(size <= 1) return; size_t i = (size-1-1)/2; for(;i > 0;i--) AdjustDown(arr,size,i); AdjustDown(arr,size,0); return; } void HeapPop(int arr[],size_t heap_size){ if(heap_size <= 1) return; Swap(&arr[0],&arr[heap_size-1]); AdjustDown(arr,heap_size-1,0); return; } void HeapSort(int arr[],size_t size){ if(size <= 1) return; HeapCreate(arr,size);//创建堆的函数 size_t i = 0; for(;i < size;i++) HeapPop(arr,size-i); //size-i表示数组中哪部分区间符合堆的规则 //即第i次删除前,[0,size-i)都是堆 return; }
- 希尔排序
希尔排序是插入排序的一种,又称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。本质上是一种分组插入的方法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
(1)插入排序在对几乎已经排好序的数据操作时,效率高;
(2)插入排序在对元素个数较少的数据操作时,效率高。
void ShellSort(int arr[],int64_t size){ int64_t gap = size/2;//使用希尔序列 for(;gap > 0;gap /= 2){//生成步长序列 int64_t bound = gap; for(;bound < size;bound++){//进行插入排序 int bound_value = arr[bound]; int64_t cur = bound; for(;cur >= gap;cur -= gap){//线性表的查找和搬运 //cur-=gap表示找到同组元素中的上一个元素 if(arr[cur-gap] > bound_value)//进行搬运 arr[cur] = arr[cur-gap]; else//找到了 break; } arr[cur] = bound_value; } } return; }