线性表是一种动态的数据结构,它的表长可以变化。线性表的功能主要是对存储在线性表中的数据进行检索,插入,删除等操作。主要有顺序表,链表两种形式。
顺序表是在一组连续地址的存储单元中存储数据,这样可以保证这些在逻辑上相邻的数据在物理上也相邻。
链表通过节点指针将数据串联起来,可以保证数据逻辑上的相邻性,但是无法保证数据物理上的相邻性。
实现方法如下:
1.建立线性表的抽象类 linearlist.h
//线性表抽象类
template <class T>
class LinearList
{
protected: //继承后派生类成员函数有访问权限
int n; //线性表长度
public:
virtual bool isEmpty() const=0; //线性表是否为空
virtual int length() const=0; //线性表长度
virtual bool find(int i,T &x) const=0; //寻找下标为i的元素,找到函数返回true,元素赋值给x
virtual int search(T x) const=0; //搜索元素x,返回该元素下标
virtual bool insert(int i,T x)=0; //在下标i出插入元素x
virtual bool del(int i)=0; //删除下标i处的元素
virtual void print() const=0; //输出线性表
};
2.顺序表的建立 seqlist.h,该顺序表public继承了上文的线性表抽象类
#include "linearlist.h"
template <class T>
class SeqList:public LinearList<T>
{
private:
T *elements;
int maxLength;
public:
SeqList(int maxLength);
~SeqList();
bool isEmpty() const;
int length() const;
bool find(int i,T &x) const;
int search(T x) const;
bool insert(int i,T x);
bool del(int i);
void print() const;
};
具体成员函数实现在 seqlist.cpp 中
#include "seqlist.h"
template <class T>
SeqList<T>::SeqList(int maxSize)
{
maxLength=maxSize;
elements=new T[maxLength];
n=0;
}
template <class T>
SeqList<T>::~SeqList()
{
delete [] elements;
}
template <class T>
bool SeqList<T>::isEmpty() const
{
return n==0;
}
template <class T>
int SeqList<T>::length() const
{
return n;
}
template <class T>
bool SeqList<T>::find(int i,T &x) const
{
if(i<0||i>n-1)
{
cout<<"寻找下标越界"<<endl;
return false;
}
x=elements[i];
return true;
}
template <class T>
int SeqList<T>::search(T x) const
{
for(int j=0;j<n;j++)
{
if(elements[j]==x)
{
return j;
}
}
return -1;
}
template <class T>
bool SeqList<T>::insert(int i,T x)
{
if(i<0||i>n)
{
cout<<"插入下标越界"<<endl;
return false;
}
if(n==maxLength)
{
cout<<"内存不足"<<endl;
return false;
}
for(int j=n-1;j>i-1;j--)
{
elements[j+1]=elements[j];
}
elements[i]=x;
n++;
return true;
}
template <class T>
bool SeqList<T>::del(int i)
{
if(!n)
{
cout<<"无可删除的元素"<<endl;
return false;
}
if(i<0||i>n-1)
{
cout<<"删除下标越界"<<endl;
return false;
}
for(int j=i+1;j<n;j++)
{
elements[j-1]=elements[j];
}
n--;
return true;
}
template <class T>
void SeqList<T>::print() const
{
for(int j=0;j<n;j++)
{
cout<<elements[j]<<'\t';
}
cout<<endl;
}
总结:
1.要注意判断下标是否越界
2.顺序表插入删除的效率较链表要低,但检索效率较链表要高
3.单链表的建立 singlelist.h ,同样也继承了第1节中的linearlist抽象类
#include "linearlist.h"
template <class T> class SingleList;
template <class T>
class Node
{
private:
Node<T> *link;
T element;
friend class SingleList<T>;
};
template <class T>
class SingleList:public LinearList<T>
{
private:
Node<T> *first;
public:
SingleList();
~SingleList();
bool isEmpty() const;
int length() const;
bool find(int i,T &x) const;
int search(T x) const;
bool insert(int i,T x);
bool del(int i);
void print() const;
};
具体成员函数实现在 singlelist.cpp 中
#include "singlelist.h"
template <class T>
SingleList<T>::SingleList()
{
first=new Node<T>;
n=0;
first->link=NULL;
}
template <class T>
SingleList<T>::~SingleList()
{
Node<T> *p;
while(first)
{
p=first;
first=first->link;
delete p;
}
}
template <class T>
bool SingleList<T>::isEmpty() const
{
return n==0;
}
template <class T>
int SingleList<T>::length() const
{
return n;
}
template <class T>
bool SingleList<T>::find(int i,T &x) const
{
if(i<0||i>n-1)
{
cout<<"find越界"<<endl;
return false;
}
Node<T> *p=first->link;
for(int j=0;j<i;j++)
{
p=p->link;
}
x=p->element;
return true;
}
template <class T>
int SingleList<T>::search(T x) const
{
int j;
Node<T> *p=first->link;
for(j=0;p&&p->element!=x;j++)
{
p=p->link;
}
if(p)
return j;
return -1;
}
template <class T>
bool SingleList<T>::insert(int i,T x)
{
if(i<0||i>n)
{
cout<<"插入元素越界"<<endl;
return false;
}
Node<T> *q=new Node<T>;
q->element=x;
Node<T> *p=first;
for(int j=0;j<i;j++)
{
p=p->link;
}
q->link=p->link;
p->link=q;
n++;
return true;
}
template <class T>
bool SingleList<T>::del(int i)
{
if(i<0||i>n-1)
{
cout<<"删除元素越界"<<endl;
return false;
}
Node<T> *q=first->link;
Node<T> *p=first;
for(int j=0;j<i;j++)
{
q=q->link;
p=p->link;
}
p->link=q->link;
delete q;
n--;
return true;
}
template <class T>
void SingleList<T>::print() const
{
Node<T> *p=first->link;
for(int j=0;j<n;j++)
{
cout<<p->element<<' ';
p=p->link;
}
cout<<endl;
}
总结:
1.该单链表的实现是带表头的单链表,在带表头的单链表中的插入删除操作可以不用考虑是否在表头插入删除的情况。