使用c++实现一下常用的数据结构,参考书为《数据结构、算法与应用-c++语言描述》。
此次代码为顺序表,为了保证通用性采用模板机制,算法本身没有什么难度,毕竟是基础算法,但是长时间不用c++,一些高级特性和陷阱着实让人难受。
此次代码共分三个文件:
1、Sq_list.h :实现顺序表的结构和基本操作。
2、excp.h :实现异常类,关于命名空间的问题,直接将异常类加入到std空间内。
3、sq.cpp :主函数,简单测试,可稍加简单修改,转为交互式程序。
Sq_list.h
//construct the sq_list with template
#ifndef _sqList_
#define _sqList_
#include <iostream>
#include "excp.h"
using namespace std;
template<class T>
class sqList {
public:
sqList(int maxSizel = 10);
~sqList(){delete [] data;}
bool isEmpty() const{return length == 0;}
template<class Type>
friend ostream& operator<<(ostream& out, const sqList<Type>& x);
int getLength() const{return length;}
bool findElement(int k, T& x) const;//get the kth value in the var x
int searchElement(T& x) const;//return the index of the var x
sqList<T>& deleteElement(int k, T& x);//remove the kth element and return it by x
sqList<T>& insertElement(int k, const T& x);//Insert x
T* getData() const {return data;}
private:
T *data;
int length;
int maxSize;
};
template<class T>
sqList<T>::sqList(int maxSizel)
{
maxSize = maxSizel;
data = new T[maxSize];
length = 0;
}
template<class T>
bool sqList<T>::findElement(int k, T& x) const
{
if (k<1 || k>length)
return false;
x = data[k-1];
return true;
}
template<class T>
int sqList<T>::searchElement(T& x) const
{
for (int i=0; i<length; i++)
if (data[i] == x)
return i+1;
return 0;
}
template<class T>
sqList<T>& sqList<T>::deleteElement(int k, T& x)
{
if (findElement(k, x))
{
for (int i=k; i<length; i++)
data[i-1] = data[i];
length--;
return *this;
}
else
throw OutOfBounds();
}
template<class T>
sqList<T>& sqList<T>::insertElement(int k, const T& x)
{
if (k<1 || k>length+1)
throw OutOfBounds();
if (length >= maxSize)
throw FullMemery();
for (int i=length-1; i>=k-1; i--)
data[i+1] = data[i];
data[k-1] = x;
length++;
return *this;
}
template<class Type>
ostream& operator<<(ostream& out, const sqList<Type>& x)
{
Type* t = x.getData();
for (int i=0; i<x.getLength(); i++)
out<<t[i]<<" ";
out<<endl;
return out;
}
#endif
excp.h
#ifndef _EXCP_
#define _EXCP_
#include <new>
using namespace std;
class OutOfBounds {
public:
OutOfBounds(){}
};
class FullMemery {
public:
FullMemery(){}
};
void my_new_handler()
{
throw FullMemery();
}
new_handler old_handler = set_new_handler(my_new_handler);
#endif
excp.h
#ifndef _EXCP_
#define _EXCP_
#include <new>
using namespace std;
class OutOfBounds {
public:
OutOfBounds(){}
};
class FullMemery {
public:
FullMemery(){}
};
void my_new_handler()
{
throw FullMemery();
}
new_handler old_handler = set_new_handler(my_new_handler);
#endif
问题总结:
1、在模板类中重载操作符,稳妥的一种方法就是像程序中这样在外层模板中(类模板)对于友元重载函数声名成另一模板,否则会提示basic_ostream找不到匹配函数什么的,估计是编译器在定义ostream的时候把所有可用的查了一遍,结果没找到合适的。
2、对于异常,使用自定义的异常,方便定制。
3、良好的编程习惯,遵循最小权限原则,对于公有函数要进行一定的限制。
4、写代码要小心,错将#ifndef写成#ifdef浪费了大量时间。