前言:这两天重新翻阅陈慧南老师编写的《数据结构——使用C++语言描述》(第2版),自己动手实现了书中的数据结构or算法。可能是为了简洁,书中有些代码没有考虑周全。我通过自己的思考实现了下,都是编译通过可以跑起来的。
接下来就愉快地开始本系列吧~
—————————————分割线——————————————
线性表类模板如下,是顺序表类和链表类的基类。
#include
using namespace std;
//线性表基类
template <typename T>
class LinearList{
protected:
int n; //线性表的长度
public:
virtual bool IsEmpty() const = 0; //若线性表空,则返回true,否则返回false
virtual int Length() const = 0; //返回表中元素个数
virtual bool Find(int i,T& x) const = 0; //在x中返回表中下标为i的元素。若不存在,则返回false,否则返回true
virtual int Search(T x) const = 0; //若x不在表中.则返回-1;否则返回x在表中的下标
virtual bool Insert(int i,T x) = 0; //在元素ai之后插入x,若i=-1,则x插在第一个元素a0前。插入成功返回true
virtual bool Delete(int i) = 0; //删除元素ai,删除成功返回true
virtual bool Update(int i,T x) = 0; //将元素ai的值修改为x,修改成功返回true
virtual void Output(ostream& out) const = 0; //把表送至输出流
};
一、线性表的顺序表示
线性表的顺序表示是用一组地址连续的存储单元依次存储线性表中的元素。这样,逻辑上相邻的元素在物理上也相邻。顺序表是一种随机存取结构,但是插入和删除时效率较低,时间主要消耗在移动元素上。移动元素的个数取决于插入或删除元素的位置。并且表的最大存储空间是预先固定的。当然也是可以扩充空间的,但是需要额外申请一个更大的空间,并且将数据复制到新空间中。
//线性表的顺序表示
template <typename T>
class SeqList:public LinearList{
private:
int maxLength; //顺序表的最大长度
T* elements; //指向顺序表的指针
public:
SeqList(int mSize);
~SeqList();
bool IsEmpty() const; //若线性表空,则返回true,否则返回false
int Length() const; //返回表中元素个数
bool Find(int i,T& x) const; //在x中返回表中下标为i的元素。若不存在,则返回false,否则返回true
int Search(T x) const; //若x不在表中.则返回-1;否则返回x在表中的下标
bool Insert(int i,T x); //在元素ai之后插入x,若i=-1,则x插在第一个元素a0前。插入成功返回true
bool Delete(int i); //删除元素ai,删除成功返回true
bool Update(int i,T x); //将元素ai的值修改为x,修改成功返回true
void Output(ostream& out) const; //把表送至输出流
};
template <typename T>
SeqList::SeqList(int mSize) {
maxLength = mSize;
elements = new T[maxLength];
this->n = 0;
}
template <typename T>
SeqList::~SeqList() {
delete[] elements;
}
template <typename T>
bool SeqList::IsEmpty() const {
return 0 == this->n;
}
template <typename T>
int SeqList::Length() const {
return this->n;
}
template <typename T>
bool SeqList::Find(int i, T &x) const {
if (i < 0 || i > this->n) {
cout << "Out of Bounds" << endl;
return false;
}
x = elements[i];
return true;
}
template <typename T>
int SeqList::Search(T x) const {
for (int i = 0; i < this->n; ++i) {
if (elements[i] == x) {
return i;
}
}
return -1;
}
template <typename T>
bool SeqList::Insert(int i, T x) {
if (i < -1 || i > this->n - 1) {
cout<<"Out of bounds"<return false;
}
if (this->n == maxLength) {
cout << "OverFlow" << endl;
return false;
}
for (int j = this->n - 1; j > i; --j) {
elements[j + 1] = elements[j];
}
elements[i + 1] = x;
this->n++;
return true;
}
template <typename T>
bool SeqList::Delete(int i) {
if (i < -1 || i > this->n - 1) {
cout<<"Out of bounds"<return false;
}
for (int j = i; j < this->n-1; ++j) {
elements[j] = elements[j + 1];
}
this->n--;
return true;
}
template <typename T>
bool SeqList::Update(int i, T x) {
if (i < -1 || i > this->n - 1) {
cout<<"Out of bounds"<return false;
}
elements[i] = x;
return true;
}
template <typename T>
void SeqList::Output(ostream &out) const {
for (int i = 0; i < this->n; ++i) {
out<" ";
}
out<
二、线性表的链接表示
链接表是由结点链接而成的,所以需要结点类Node。链表不能随机存取数据,并且插入和删除算法的时间复杂度同顺序表上插入和删除的时间复杂度一样,也是O(n)。顺序表插入和删除的时间主要花在移动元素上,而链表主要花在查找元素上。链表的一个好处就是大小不用固定。
本次实现的是带有表头结点的单链表。
//线性表的链接表示,带表头结点的单链表
template <typename T>
class SingleList;
template <typename T>
class Node{
private:
T element;
Node *next;
friend class SingleList;
};
template <typename T>
class SingleList:public LinearList {
private:
Node* head;
public:
SingleList();
~SingleList();
bool IsEmpty() const; //若线性表空,则返回true,否则返回false
int Length() const; //返回表中元素个数
bool Find(int i,T& x) const; //在x中返回表中下标为i的元素。若不存在,则返回false,否则返回true
int Search(T x) const; //若x不在表中.则返回-1;否则返回x在表中的下标
bool Insert(int i,T x); //在元素ai之后插入x,若i=-1,则x插在第一个元素a0前。插入成功返回true
bool Delete(int i); //删除元素ai,删除成功返回true
bool Update(int i,T x); //将元素ai的值修改为x,修改成功返回true
void Output(ostream& out) const; //把表送至输出流
};
template <typename T>
SingleList::SingleList() {
head = new Node;
head->next = NULL;
this->n = 0;
}
template <typename T>
SingleList::~SingleList() {
Node *p;
while (head != NULL) {
p = head;
head = head->next;
delete (p);
}
}
template <typename T>
bool SingleList::IsEmpty() const {
return 0 == this->n;
}
template <typename T>
int SingleList::Length() const {
return this->n;
}
template <typename T>
bool SingleList::Find(int i, T &x) const {
if (i < -1 || i > this->n - 1) {
cout<<"Out of bounds"<return false;
}
Node* p = head;
for (int j = 0; j <= i; ++j) {
p = p->next;
}
x = p->element;
return true;
}
template <typename T>
int SingleList::Search(T x) const {
Node *p = head->next;
int i = -1;
while (p != NULL) {
i++;
if (p->element == x) {
return i;
}
}
return -1;
}
template <typename T>
bool SingleList::Insert(int i, T x) {
if (i < -1 || i > this->n - 1) {
cout<<"Out of bounds"<return false;
}
Node* p = head;
for (int j = 0; j <= i ; ++j) {
p = p->next;
}
Node *newNode = new Node;
newNode->element = x;
newNode->next = p->next;
p->next = newNode;
this->n++;
return true;
}
template <typename T>
bool SingleList::Delete(int i) {
if (i < -1 || i > this->n - 1) {
cout<<"Out of bounds"<return false;
}
Node *p = head;
for (int j = 0; j < i; ++j) {
p = p->next;
}
Node *tmp = p->next;
p->next = p->next->next;
delete (tmp);
this->n--;
return true;
}
template <typename T>
bool SingleList::Update(int i, T x) {
if (i < -1 || i > this->n - 1) {
cout<<"Out of bounds"<return false;
}
Node *p = head;
for (int j = 0; j <= i; ++j) {
p = p->next;
}
p->element = x;
return true;
}
template <typename T>
void SingleList::Output(ostream &out) const {
Node *p = head->next;
while (p != NULL) {
out<element<<" ";
p = p->next;
}
out<
最后的测试代码:
int main() {
int n = 10;
LinearList<int> *linearList = new SeqList<int>(n);
//LinearList *linearList = new SingleList();
for (int i = 0; i < n; ++i) {
linearList->Insert(i-1, i);
}
linearList->Output(cout);
linearList->Delete(2);
linearList->Output(cout);
linearList->Update(3, 10);
linearList->Output(cout);
return 0;
}