目录
排序算法
快排
快排与归并的区别:两者均属于分治算法 ,然而归并是归并需要O(n),快排是问题划分需要O(n)。快排的问题在于划分出来的子问题并不一定均衡,其最坏情况下O(nlogn)的复杂度,然而其大多数情况下性能均强于别的排序算法。
思路:选取一个pivot,使得pivot将数组分为两个部分,pivot前的均小于pivot,后的均大于pivot
数组 【lo,hi】->选取pivot,从两端交替比较与pivot的大小,将pivot放在其应该的位置上,返回这个位置mi->将远问题分解为[lo,mi]&[mi+1,hi]->直到hi-lo<2终止。
int partition(vector<double>& xx, int lo, int hi)
{
swap(xx[lo], xx[lo + rand() % (hi - lo+1)]);
double pivot = xx[lo];
while (lo<hi)
{
while ((lo < hi) && (pivot <= xx[hi]))
hi--;
xx[lo] = xx[hi];
while ((lo < hi) && (xx[lo] <= pivot))
lo++;
xx[hi] = xx[lo];
}
xx[lo] = pivot;
return lo;
}
void quicksort(vector<double>& v_d, int lo, int hi)//lo hi为数组首位角标
{
if (hi - lo < 2) return;
int mi = partition( v_d, lo, hi);
quicksort(v_d, lo, mi);
quicksort(v_d, mi + 1, hi);
}
选取与中位数
众数
A中有一半以上的元素数值都是m,则m为A的众数。
思路:
选出候选众数maj
核实maj是否为众数
int maj_find(vector<int> A)
{
int maj;
for (int c = 0, i = 0; i != A.size(); i++)
{
if (0 == c)
{
maj = A[i]; c = 1;
}
else
{
maj == A[i] ? c++ : c--;
}
}
return maj;
}
bool maj_check(vector<int>A, int maj)
{
int counts(0);
for (auto a : A)
if (a == maj)
counts++;
return 2 * counts > A.size();
}
bool maj_fun(vector<int> A, int & maj)
{
maj=maj_find(A);
return maj_check(A, maj);
}
归并向量的中位数
归并两个有序向量时候,可以比较两个向量的中间元素大小,可将问题规模减半。递归深度不超过logn 时间复杂度O(logn)
k-选取问题
- 构建n大小的小顶堆,经过k次dlmin,O(n)+kO(logn)
- 任取k个构建大顶堆,依次插入后维护,O(k)+2(n-k)O(logk)
- 构建一个n-k的小顶堆,k的大顶堆,然后反复比较堆顶元素O(n-k)+O(k)+min(k,n-k)*2*(O(lgk+lg(n-k)))
希尔排序(shellsort)
将A[]->B[][]
B[i][j]=A[iw+j]
w1<w2<...<size
将A分为w1列,然后逐行排序,排完之后再将其分为w2。。。。迭代直到w>size
shell序列[w1,w2,w3...]尽量互为素数