数据结构静态的描述了数据元素之间的关系。
高效的程序需要在数据结构的基础上设计和选择算法。
高效的程序:恰当的数据结构+合适的算法
算法是特定问题求解步骤的描述:在计算机中表现为指令的有限序列。算法是独立存在的一种解决问题的方法和思想。特性:
输入:算法具有0个或多个输入。
输出:算法至少有1个或多个输出。
有穷性:算法在有限的步骤之后会自动结束而不会无限循环。
确定性:算法中的每一步都有确定的含义,不会出现二义性。
可行性:算法的每一步都是可行的。
正确性:算法对于合法数据能够得到满足要求的结果。算法能够处理非法输入,并得到合理的结果。算法对于边界数据和压力数据都能得到满足要求的结果。
可读性:算法要方便阅读,理解和交流。
健壮性:算法不应该产生莫名其妙的结果。
性价比:利用最少的资源得到满足要求的结果。
算法复杂度:
时间复杂度:算法运行后对时间需求量的定性描述。
空间复杂度:算法运行后对空间需求量的定性描述。
大O(operation)表示法:关注操作数量的最高次项。
6、算法效率
O(1) 算法的空间复杂度:S(n)=S(f(n)),n为算法的问题规模,f(n)为空间使用函数,与n有关 。 问题:在一个自然是1-1000中找出出现次数最多的数字 /* 题目:当两个算法的大O表示法相同时,是否意味着两个算法的效率完全相同? 7、数据结构该怎么学习? 1,先从概念上形象的理解数据元素之间的关系。 2、思考这种关系能够解决什么问题。 3、考虑基于这种关系能够产生哪些算法。 4、理解和熟悉最终的算法。 5、选择一种熟悉的语言,编码实战。 8、泛型编程: c++中的类模板:以相同的方式处理不同的类型。在类声明之前用template进行标识, #include using namespace std; } }; } 函数模板支持参数的自动推导和显示指定,类模板在使用时只能显示指定类型,类模板非常适用于编写数据结构相关的代码。 9、智能指针 指针生命周期结束时主动释放堆空间,一片堆空间最多只能由一个指针标识(拷贝构造函数,重载赋值操作符),杜绝指针运算和指针比较。 设计方案:通过类模板描述指针的行为,能够定义不同类型的指针对象。 重载指针特征操作符(->和*),利用对象模拟原生指针的行为。 创建DTLib . 智能指针 #ifndef SMARTPOINTER_H_ #endif #include } 智能指针的使用军规:智能用来指向堆空间的单个对象或者单个变量(不能是数组或者局部对象或者局部变量) 指针特征操作符(->和*可以被重载),重载指针特征符能够使用对象代替指针,智能指针智能用于指向堆空间中的内存,智能指针最大程度的避免内存问题。 11、异常的类型可以是自定义类类型,对于类类型异常的匹配依旧是至上而下严格匹配,赋值兼容性原则在异常匹配中依然适用。匹配子类异常的catch放在上部,匹配父类异常的catch放在下部。 异常功能定义: Arithmenticption 计算异常 NullpointerException 空指针异常 indexOutOfBoundsException 越界异常 NoEnoughMemoryException内存不足异常 InvalidParameterException 参数错误异常 #ifndef EXCEPTION_H_ #endif #include "Exception.h" } #include //设计原则:在可复用代码库设计时,尽量使用面向对象技术进行架构,尽量使用异常处理机制分离正常逻辑和异常逻辑 //现代c++库必然包含充要的异常类族,所有库中的数据结构类都依赖于异常机制,异常机制能够分离库中代码的正常逻辑和异常逻辑 12、顶层父类 当代软件架构实践中的经验:尽量使用单重继承的方式进行系统设计,尽量保持系统中只存在单一的继承树,尽量使用组合关系代替继承关系。 不幸的事实:c++语言的灵活性使得代码中可以存在多个继承树,c++编译器的差异使得同样的代码可能表现不同的行为。 比如new操作失败会发生什么? 创建Wobject类的意义:遵循经典设计准则,所有数据结构都继承自Wobject,定义动态内存申请的行为,提高代码的移植性。 #ifndef Wobject_H_ //析构函数为纯虚函数,为抽象类,保证所有子类有虚函数表指针,能够使用动态类型识别相关的技术 #include free(p); //在堆中创建Wobject子类的对象,失败时返回NULL值,Wobject类为纯虚父类,所有子类都能进行动态类型识别 13、类族结构的进化 所有类位于单一的继承树,Wobject定义了动态内存申请失败时返回空指针。 改进的关键点,Exception类继承自Wobject类,堆空间中创建异常对象失败时,返回NULL指针。 新增InvalidOperation异常类:成员函数调用时,如果状态不正确则抛出异常。 SmartPoint类继承自Wobject类,堆空间中创建智能指针对象失败时,返回NULL 指针。 /* WSlib的开发方式和注意事项
问题:
在一个由自然数1-1000中某些数字所组成的数组中,每个数字可能出现零次或者多次。
设计一个算法,找出出现次数最多的数字。
*/
#include
using namespace std;
void search(int a[], int len) // O(n)
{
int sp[1000] = {0};
int max = 0;
for(int i=0; i
sp[a[i] - 1]++; //作为sp数组的下标
}
for(int i=0; i<1000; i++)
{
if( max < sp[i] )
{
max = sp[i];
}
}
for(int i=0; i<1000; i++)
{
if( max == sp[i] )
{
cout << i + 1 << endl;
}
}
}
int main(int argc, char* argv[])
{
int a[] = {1, 1, 3, 4, 5, 6, 6, 6, 3, 3};
search(a, sizeof(a)/sizeof(*a));
return 0;
}
void Swap(T& a, T& b)
{
T t = a;
a = b;
b = t;
class Op
{
public:
T process(T v)
{
return v * v;
}
{
int a = 2;
int b = 1;
Swap(a, b);
cout << "a = " << a << " " << "b = " << b << endl;
double c = 0.01;
double d = 0.02;
Swap
cout << "c = " << c << " " << "d = " << d << endl;
Op
Op
cout << "5 * 5 = " << opInt.process(5) << endl;
cout << "0.3 * 0.3 = " << opDouble.process(0.3) << endl;
return 0;
#define SMARTPOINTER_H_
namespace WSlib
{
template
class SmartPointer
{
T* m_pointer;
public:
SmartPointer(T* p=NULL)
{
m_pointer=p;
}
SmartPointer(const SmartPointer
{
m_pointer=obj.m_pointer;
const_cast
}
SmartPointer
{
if(this != &obj)
{
delete m_pointer;
m_pointer=obj.m_pointer; //this->m_pointer=obj.m_pointer;
//两者都是二元操作符,而且右边的操作数都是成员的名称。
// 不同点:点运算符( . )的左边操作数是一个结果为结构的表达式;
// 箭头运算符( -> )的左边的操作数是一个指向结构体的指针
const_cast
}
return *this; //可以支持连续赋值
}
T* operator ->()
{
return m_pointer;
}
T* operator* ()
{
return *m_pointer;
}
bool isNull()
{
return (m_pointer==NULL);
}
T* get()
{
return *m_pointer;
}
~SmartPointer()
{
delete m_pointer;
}
};
}
#include "SmartPointer.h"
using namespace std;
using namespace WSlib; //必须使用自己命名空间
class Test
{
public:
Test()
{
cout<<"Test()"<
~Test()
{
cout<<"~Test()"<
};
int main()
{
SmartPointer
SmartPointer
nsp=sp;
//nsp++; 错的
cout<
#define EXCEPTION_H_
namespace WSlib
{
#define THROW_EXCEPTION(e, m) (throw e(m,__FILE__,__LINE__))
class Exception
{
protected:
char* m_message; //指向字符串,异常详细信息
char* m_location; //异常地点
void init(const char* message,const char* file,int line);//重载了构造函数,构造函数内部逻辑差不多,利用辅助函数完成初始化
public:
Exception(const char* message);
Exception(const char* file,int line);
Exception(const char* message,const char* file,int line);
Exception(const Exception& e);
Exception& operator=(const Exception& e);
virtual const char* message()const;
virtual const char* location()const;
virtual ~Exception()=0; //纯虚析构函数,用来说明当前类时抽象类
};
class ArithmeticException:public Exception
{
public:
ArithmeticException():Exception(0){}
ArithmeticException(const char* message):Exception(message){}
ArithmeticException(const char* file,int line):Exception(file,line){}
ArithmeticException(const char* message,const char* file,int line):Exception(message,file,line){}
ArithmeticException(const ArithmeticException& e):Exception(e){}
ArithmeticException& operator=(const ArithmeticException& e)
{
Exception::operator=(e); //直接调用父类的赋值操作符重载函数
return *this;
}
};
}
#include
#include
using namespace std;
namespace WSlib
{
void Exception::init(const char* message,const char* file,int line)
{
//m_message=message;直接赋值不行,参数message指针指向字符串可能在栈,堆空间,全局数据区,没有办法控制message所指向的外部字符串的生命周期
m_message=strdup(message); //strdup将字符串复制到堆空间,m_message就指向堆空间的字符串,他的内容与message指向的字符串一样
if(file!=NULL)
{
char sl[16]={0};
itoa(line,sl,10);
m_location=static_cast
m_location=strcpy(m_location,file);
m_location=strcat(m_location,":");
m_location=strcat(m_location,sl);
}
else
{
m_location=NULL;
}
}
Exception::Exception(const char* message)
{
init(message,NULL,0);
}
Exception::Exception(const char* file,int line)
{
init(NULL,file,line);
}
Exception::Exception(const char* message,const char* file,int line)
{
init( message,file, line);
}
Exception::Exception(const Exception& e) //深拷贝,要保证每个对象内部的成员指针所指向的都是独立的堆空间
{
m_message=strdup(e.m_message);
m_location=strdup(e.m_location);
}
Exception& Exception::operator=(const Exception& e)
{
if(this!=&e)
{
free(m_message);
free(m_location);
m_message=strdup(e.m_message);
m_location=strdup(e.m_location);
}
return *this;
}
const char* Exception::message() const
{
return m_message;
}
const char* Exception::location() const
{
return m_location;
}
Exception::~Exception() //纯虚函数不提供实现,实现由子类完成,析构函数例外:c++规定,但凡自定义了析构函数,不管是不是纯虚函数,都要提供实现,因为析构对象时,最后都要调用父类析构函数,如果父类析构函数是纯虚函数并且没有实现,当调用到顶层析构函数时,没有实现不可以
{
free(m_message);
free(m_location);
}
#include "Exception.h"
using namespace std;
using namespace WSlib;
int main()
{
try
{
THROW_EXCEPTION(ArithmeticException, "test");
//throw Exception("test",__FILE__,__LINE__); //文件名和行号使用预定义的宏 __FILE__,__LINE__
}
catch(const Exception&e)
{
cout<<"catch(const Exception& e)"<
catch(const ArithmeticException& e) //异常匹配自上往下,捕获类型有继承关系,子类放上面,父类放下面,这个应该放上面
{
cout<<"catch(const Exception& e)"<
return 0;
#define Wobject_H_
namespace WSlib
{
class Wobject
{
public:
void* operator new(unsigned int size)throw();
void operator delete(void* p);
void* operator new[](unsigned int size)throw();
void operator delete[](void* p);
virtual ~Wobject()=0;
};
}
#endif
//定义我们自己的new/delete重载函数,new/delete数据结构库中类的对象时,有我们期望的行为,在各个编译器都是一样的
#include "Wobject.h"
#include
using namespace std;
namespace WSlib
{
void* Wobject::operator new(unsigned int size)throw() //throw()不会抛出异常,失败返回空值
{
cout<<"Wobject::operator new"<
}
void Wobject::operator delete(void* p)
{
cout<<"Wobject::operator delete"<
}
void* Wobject::operator new[](unsigned int size)throw() //throw()不会抛出异常,失败返回空值
{
return malloc(size);
}
void Wobject::operator delete[](void* p)
{
free(p);
}
Wobject::~Wobject()
{
}
}
/* 测试用例
#include
#include "Wobject.h"
using namespace std;
using namespace WSlib;
class Test:public Wobject
{
public:
int i;
int j;
};
class Child:public Test
{
public:
int k;
};
int main()
{
Wobject* obj1=new Test();
Wobject* obj2=new Child();
cout<<"obj1"<
delete obj1;
delete obj2;
return 0;
}
****************************结果*******************************************
/*Wobject::operator new12 两个整形,一个虚函数表指针
Wobject::operator new16 又定义了一个整形k
obj100FFE238
obj200FFA1D8
Wobject::operator delete00FFE238
Wobject::operator delete00FFA1D8 释放对象空间的是我们自己定义的
**************************************************************************/
//Wobject类是WSlib中数据结构类的顶层父类,Wobject类用于统一动态内存申请的行为(失败返回空值,而不是抛出标准库中的异常对象),
迭代开发(可能推翻上一次的程序):每次完成一个小的目标,持续开发,最终打造可复用类库。原则:
单一继承树:所有类都继承自Wobject,规范堆对象创建时的行为
只抛异常,不处理异常:使用THROW_EXCEPTION抛出异常,提高移植性
弱耦合性:尽量不适用标准库中的类和函数,提高可移植性*/