一、 导论
1. 【算法】:算法是完成特定任务的有限指令集。所有的算法必须满足下面的标准:
1) 输入。由外部提供零个或多个输入量。
2) 输出。直到产生一个输出量。
3) 明确性。每条指令必须清楚,不具模糊性。
4) 有限性。如果跟踪算法的指令,那么对于所有的情况,算法经过有限步以后终止。
5) 有效性。每条指令必须非常基础,原则上使用笔和纸就可以实现。
2. 【复杂度】:算法的空间复杂度是其运行所需的存储空间。算法的时间复杂度是其运行所需的计算时间。
二、 分治算法
1. 给定一个有n个输入的函数,分治策略建议将输入分为k个不同的子集,1<k<=n,从而产生k个子问题。
2. 二叉查找
int BinSrh ( Type a[] ,int i ,int l ,Type x )
{
if ( l ==1 ){
if ( x ==a[i] ) return i
else return 0;
};
else {
int mid = ( i + 1 ) / 2;
if ( x == a[mid] ) return mid;
else if ( x < a[mid] ) return BinSrch ( a ,I ,mid - l ,x );
}
}
3. 非递归二叉查找
int BinSearch ( Type a[] ,int n ,Type x )
{
int low = 1 ,high=n;
while ( low <= high ){
int mid = ( low + high ) / 2;
if ( x < a[mid] ) high = mid – 1;
else if ( x > a[mid]) low = mid + 1;
else return ( mid );
}
return ( 0 );
}
4. 查找最大值和最小值
void StraightMaxMin ( Type a[] ,int n ,Tyep& max , ,Tyep& min )
{
max = min = a[1];
for ( int I = 2 ;I < n ; i++ ){
if ( a[i] > max ) max = a[i];
if ( a[i] <min ) min = a[i];
}
}
这种算法在最好,平均和最坏情况下,函数StraightMaxMin都要做2(n-1)次元素比较。
if( a[i] > max ) max = a[i];
else if ( a[i] < min ) min = a[i];
现在,最好的比较次数为n-1,最坏比较次数为2(n-1)。
5. 查找最大值和最小值(递归)
void MaxMin ( int I ,int j ,Type& max , ,Tyep& min )
{
if ( I == j ) max = min = a[i];
else if ( I == j-1 ){
if ( a[i] < a[j] ) { max = a[j]; min = a[i];}
else { max = a[i]; min = a[j];}
}
else{
int mid = ( I + j ) / 2;
Type max1 ,min1;
MaxMin ( I ,mid ,max ,min )
MaxMin ( mid + 1 ,j ,max1 ,min1 )
if ( max < max1 ) max = max1;
if ( min > min1 ) min = min1;
}
}
现在递推关系为: T([n/2]) + T([n/2]) + 2 n>2
T(n)= 1 n=2
0 n=1
当n为2的幂时,3n/2-2是最好,平均和最坏情况下的比较次数。
6. 归并排序
void MergeSort ( int low ,int high )
{
if ( low < high ){
int mid = ( low + high ) / 2;
MergeSort ( low ,mid );
MergeSort ( mid+1 ,high );
Merge ( low ,mid ,high );
}
}
void Merge ( int low ,int mid ,int high )
{
int h = low ,i = low ,j = mid + 1 ,k;
while ( ( h <= mid ) && ( j <= high ) ){
if ( a[h] <= a[j] ) { b[i] = a[h]; h++;}
else { b[i] = a[j]; j++;}
}
if ( h > mid ) for ( k = j ;k < high ;k++ ){
b[i] = a[k];
i++;
}
else for( k = h ;k <= mid ;k++ ){
b[i] = a[k];
i++;
}
for ( k = low ;k <= high ;k++ ) a[k] = b[k];
}
现在递推关系为: a n=1,a为常数
T(n)=
2T(n/2)+cn n>1,c为常数
当n为2的幂时,T(n) = O(n logn)
7. 归并排序(链表)
1) 插入排序
void InsertionSort ( Type a[] ,int n )
{
for ( int j = 2 ;j<=n ;j++ ){
Type item = a[j]; int i = j – 1;
while ( ( I >= 1 ) && ( item < a[i] ) ){
a[i+1] = a[i]; i--;
}
a[i+1]=item;
}
}
2) 使用链的归并排序
int MergeSort1 ( int low ,int high )
{
if ( ( high – low + 1 ) < 16 )
return InsertionSort1 ( a ,link ,low ,high );
else {
int mid = ( low + high ) / 2;
int q = MergeSort1 ( low ,mid );
int r = MergeSort1 ( mid + 1 ,high );
return ( Mege1 ( q ,r ) );
}
}
3) 归并有序元素的链表
int Mege1 ( int q ,int r )
{
int I = q ,j = r ,k = 0;
while ( I && j ) {
if ( a[i] <= a[j] ) {
link[k] = i; k = i; i = link[i];
}
else {
link[k] = j; k = j; j = link[j];
}
}
if ( !i ) link[k] = j;
else link[k] = i;
return ( link[0] );
}
8. 快速排序
int Partiton ( Type a[] ,int m ,int p )
{
Type v = a[m]; int I = m ,j = p;
do{
do i++;
while ( a[i] < v );
do j--;
while ( a[j] > v );
if ( I < j ) Interchange ( a ,I ,j );
}while ( I < j );
a[m] = a[j]; a[j] = v; return ( j );
}
inline void Interchange ( Type a[] ,int i ,int j )
{
Type p = a[i];
a[i] = a[j]; a[j] = p;
}
void QuickSort ( int p ,int q ) //递归
{
if( p < q ){
int j = Partition ( a ,p ,q+1 );
QuickSort ( p ,j - 1 );
QuickSort ( j + 1 ,q );
}
}
void QuickSort2( int p ,int q ) //迭代
{
Stack<int> stack( SIZE ) //SIZE is 2 * log(n)
do{
while ( p < q ){
int j = Partition ( a ,p ,q + 1 );
if ( ( j - p ) < ( q - j ) ){
stack.Add ( j + 1 );
stack.Add ( q );
q = j -1;
}
else{
stack.Add ( p );
stack.Add ( j - 1 );
p = j + 1;
}
}
if ( stack.stackEmpty() ) return;
stack.Delect ( q );
stack.Delect ( p );
}while ( 1 );
}
9. 随机快速排序算法
void RQuickSort ( int p ,int q )
{
if ( p < q ){
if ( ( q - p ) > 5 ) Interchange ( a ,random() % ( q – p + 1 ) + p ,p );
int j = Partition ( a ,p ,q + 1 ;
RQuickSort ( p ,j - 1 );
RQuickSort ( j + 1 ,q );
}
}
10. 查找第k最小元素
void Select1 ( Type a[] ,int n ,int k )
{
int low = 1 ,up = n + 1;
a [n+1] = INFTY; //a[n+1] is set to infinity
do{
int j = Partition ( a ,low ,up );
if ( k == j ) return;
else if ( k < j ) up = j;
else low = j + 1;
}while (1);
}
void Select2 ( Type a[] ,int k ,int low ,int up )
{
do{
int n = up – low +1;
if ( n <= r ){
InsertionSort ( a ,low ,up );
return ( low + k -1 );
}
for ( int I = 1 ;I <= ( n / r ) ; i++ ){
InsertionSort ( a ,low + ( i - 1 ) * r ,low + i * r -1);
Interchange ( a ,low + I -1 , low + ( I - 1 ) * r + Ceil ( r ,2 ) - 1 );
}
int j = Select2 ( a ,Ceil ( n / r ,2 ) ,low ,low + ( n / r ) - 1 );
Interchange ( a ,low ,j );
j = Partition ( a ,low ,up + 1 );
if ( k == ( j – low + 1 ) ) return (j);
else if ( k < ( j – low + 1 ) ) up = j – 1;
else { k -= ( j – low + 1 ); low = j + 1;}
}while(1);
}
int Ceil ( int a ,int b )
{
if ( ( a % b ) == 0 ) reutn ( a/b );
else return ( (a/b) + 1 );
}
11. Graham扫描算法(如果S为平面中的点的集合,Graham扫描算法从S中找出有最小的y坐标的点p(通过选出最左边的点打破平局)。然后根据点和p连线与正x轴所称的角度讲S中的点排序。)
#define NIL 0
#include <iostream.h>
struct point {
float x ,y;
struct point *prev ,*next;
};
typedef struct point Type;
class PointSet
{
private:
Type* ptslist;
float Area ( float ,float ,float ,float ,float ,float );
void PrintList ( Type * );
void Scan ( Type * );
coid Sort ( Type * );
public:
PointSet() {ptslist = NIL; }
void Insert ( float a ,float b );
void ConvexHull ( );
};
void PointSet :: Scan ( Type* list)
{
Type *p = list, *p1 = list, *p2, *p3;
float temp;
do{
p2 = p1->next;
if ( p2->next ) p3 = p2->next;
else p3 = p;
temp = Area ( p1->x ,p1->y ,p2->x ,p2->y ,p3->x ,p3->y );
if ( temp >= 0.0 ) p1 = p1->next;
else{
p1->next = p3;
p3->prev = p1;
delete p2;
p1 = p1->prev;
}
}while ( !( ( p3 == p ) && ( temp >= 0.0 ) ) );
}
void PointSet :: ConvexHull( )
{
Sort ( ptslist );
Scan ( ptslist );
PrintList ( ptslist );
}
三、贪心算法(待续……)