1.排序算法
1.1 插入排序
1.1.1 概念
1.1.2 代码
void insertionSort(int arr[], int len)
{
int insertPosi;
for (int i = 0; i < len; i++)
{
insertPosi = 0; //can't find the bigger position then keep the insertPosi 0
//find the insert position
for (int j = i - 1; j >= 0; j--)
{
if (arr[j] <= arr[i])
{
insertPosi = j + 1; //insert at arr[j + 1], minimum of inserPosi is 1 int the loop;
break;
}
}
//same position as i, just keep it
if (insertPosi == i)
continue;
//copy from [j + 1, i - 1] -> [j + 2, i]
//namely copy from [insertPosi, i) -> [insertPosi + 1], i + 1)
int temp = arr[i];
for (int k = i - 1; k >= insertPosi; k--)
{
arr[k + 1] = arr[k];
}
arr[insertPosi] = temp;
}
}
1.1.3 时间复杂度分析
查找插入位置的效率 在 O(1)~O(n)浮动
1)当输入序列已经有序时,该算法中的查找插入位置仅需O(1)时间,
即第一次判断 arr[j] <= arr[i],就成立了,就完成搜索了;
累计需要O(n)的时间,n*O(1)。
2)当输入序列完全逆序,则各次查找插入位置需要线性时间;
即每次都要判断线性长度次,比如将第i个元素插入到前面[0,i)的有序
序列中,需要搜索 i-1 次。
这样搜索完所有的长度,累计需要 O(n2) 时间,1+2+3+……+n的级别。
另外,向后复制的次数和搜索的向前遍历的次数是一样的,所以,总的时间是
2倍于搜索所需时间,常数2可以抹去。
总结
1)在等概率条件下,平均仍需要 O(n2) 时间。
2)输入敏感性很强,时间取决于逆序对的数目!!!
1.2 归并排序
1.2.1 概念
1.2.2 代码
/***************sort 2: mergeSort***************
***********************************************/
void mergeSort(int arr[], int len)
{
mergeSortCore(arr, 0, len);
}
/*
[lo, hi)
*/
void mergeSortCore(int arr[], int lo, int hi)
{
if (hi - lo < 2) return;
int mi = (lo + hi) / 2;
mergeSortCore(arr, lo, mi);
mergeSortCore(arr, mi, hi);
merge(arr, lo, mi, hi);
}
/*
二路有序数组的归并,
[lo, mi)
[mi, hi)
复杂度分析:
每经过一次迭代,j和k至少有一个会+1,
merge总体迭代不会超过O(n)
*/
void merge(int arr[], int lo, int mi, int hi)
{
int* A = arr + lo;
int lb = mi - lo;
int* B = new int[lb];
for (int i = 0; i < lb; B[i] = A[i++]);
int lc = hi - mi;
int* C = arr + mi;
//1.精简实现
//循环条件是复制出来的B序列还没全部插入排序
//如果B已经全部插入排序,C序列本身与A序列共享内存,不需要再做搬运复制工作
for (int i = 0, j = 0, k = 0; j < lb; )
{
//C序列还没全部插入,并且比B序列当前的小
if (k < lc && C[k] < B[j])
A[i++] = C[k++];
//C序列已经全部插入,或者 B序列当前的比C序列的小
if (lc <= k || B[j] <= C[k])
A[i++] = B[j++];
}
//2.复杂实现
// for (int i = 0, j = 0, k = 0; (j < lb) || (k < lc); )
// {
// if ((j < lb) && (!(k < lc) || (B[j] <= C[k])))
// A[i++] = B[j++];
// if ((k < lc) && (!(j < lb) || (C[k] < B[j])))
// A[i++] = C[k++];
// }
delete [] B;
}
1.2.3 时间复杂度分析
归并排序
O(nlogn) 是根据递推式得出来的,根据分而治之策略,
T(n)