生活中大家从小到大处处可见排队,但是排队有哪些快速的方法你了解吗?



void InsertSort(int* a, int n)
{//[0,end]有序,把 end+1位置的值插入[0,end],让[0,end+1]有序for (int i = 0; i < n - 1; ++i)//这里的for循环,就相当于摸牌,n-1就相当于斗地主中,非地主一共摸几张{int end = i;int tmp = a[end + 1];while (end >= 0){if (a[end] > tmp){a[end + 1] = a[end];--end;}else{break;}}a[end + 1] = tmp;}
}
void TestInsertSort()
{int a[] = { 3,5,2,7,8,6,1,9,4,0 };InsertSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}
希尔排序是直接插入排序的优化,又被称为“缩小增量排序”,虽然它也是一种属插入排序类的方法,但是时间效率相比直接插入排序有较大改进。😎😎😎
大致分为两步:1.预排序让数组接近有序,2.直接插入排序(上面直插总结,元素越接近有序,直插效率越高)。
先选一个整数(gap),把数组中间隔为gap的分为一组,并将每组排好序,再让gap/2,并重复分组和排序,当gap=1时,数组中就排好序了。 其中每组排序用的是直接插入排序

void ShellSort(int* a, int n)
{int gap=n;while (gap > 1){//gap=gap/3+1;gap = gap / 2;//除三或者除二都是可以的,除二的话能保证最后gap一定为1// gap>1时都是预排序--目的使其接近有序// gap==1时就是直接排序//gap很大时,下面预排序的时间复杂度是O(N)// gap很小时,数组已经很接近有序了,这是差不多是O(N)//把间隔为gap的多组数据同时排for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}
void TestShellSort()
{int a[] = { 9,8,7,6,5,4,3,2,1,0 };ShellSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,最大的放到序列的最后面,直到全
部待排序的数据元素排完 。😧😧😧
实现

void Swap(int*p1,int*p2)//交换
{int* tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;while (begin < end){int min = begin, max = begin;for (int i = begin; i <= end; ++i){//分别选出数组中最大的数和最小的数,分别赋给min和max;if (a[i] < a[min]){min = i;}if (a[i] > max){max = i;}}Swap(&a[begin], &a[min]);// 如果begin跟max重叠,需要修正一下max的位置if (begin == max){max = min;}Swap(&a[max], &a[end]);++begin;--end;}
}void TestSelectSort()
{int a[] = { 3, 5, 2, 7, 8, 6, -1, 9, 9, 4, 0 };SelectSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}
- 直接选择排序很简单,只看代码就能轻松理解,但是实用性很低,大家了解即可;
- 时间复杂度:O(N^2);
- 稳定性:不稳定。
之前在二叉树中写过链式结构,今天的堆排序顺带着给大家写一下二叉树的顺序结构。
堆的逻辑结构与物理结构
堆的两大特性

建小堆:选出左右孩子中小的哪一个,跟父亲交换,小的往上浮,大的往下沉,如果要建大堆则相反
向下调整算法前提
向下调整算法基本思想(以小堆为例子)
如何选择建大堆还是小堆?
因为我们这里用到的是升序,所以就用大堆的方式
先将一个数组构建一个大顶堆,此时,最大值就是根结点,将其与末尾元素进行交换,这时末尾就是最大值,然后再将剩余n-1个元素再次构建一个大顶堆,以此循环,就可以得到一个有序序列。😋😋😋
//交换两个变量--传址调用
void Swap(int*p1,int*p2)
{int* tmp = *p1;*p1 = *p2;*p2 = tmp;
}
//向下调整算法--大堆
void AdjustDwon(int* a, int n, int root)
{int parent = root;int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] > a[child]){child += 1;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}void HeapSort(int* a, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDwon(a, n, i);}int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDwon(a, end, 0);--end; }
}
void TestHeapSort()
{int a[] = { 3, 5, 2, 7, 8, 6, 1, 9, 4, 0 };HeapSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}
😊😊😊到了这里大家对于插入排序和选择排序这两类已经基本掌握了,下篇会得大家带来冒泡排序,三种快速排序,计数排序和归并排序。😚😚😚
上一篇:【C++笔试强训】第十一天