线性表( Linear List )的定义,线性表是零个或多个具有相同类型的数据元素的有限序列。数据元素的个数定义为线性表的长度 。长度等于零时称为空表,。
一个非空表通常记为 L = ( a 1 , a 2 ,……, a n ) 其中, a i ( 1 ≤ i ≤ n )称为数据元素,下标 i 表示该元素在线性表中的位置或序号, 称元素 a i 位于表的第 i 个位置,或称 a i 是表中的第 i 个元素。
线性表中的数据元素具有相同类型,相邻元素具有前驱和后继关系。
线性表又分为顺序表和链表。
顺序表
线性表的顺序存储是指用一组地址连续的存储单元(数组)依次存储线性表中的各个元素,线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。
顺序存储的实现:一维数组存储顺序表中的数据
#include<iostream>
using namespace std;
const int Maxsize=100;
template<class T>
class SeqList
{
private:
T data[Maxsize];
int length;
public:
SeqList();//构造函数,构造一个空的顺序表
SeqList(T a[],int n);//构造函数,根据提供的数组和元素个数创建非空顺序表
~SeqList(){}//析构函数
int Length(){return length;}//返回顺序表现有的元素个数
void Insert(int i,T x);//根据i的位置,将x插入到i位置处
T Delete(int i);//根据i位置删除i位置处的元素
void PrintList();//输出所有的元素
int Weizhi(int x);//根据x的值,输出x的位置
};
template<class T>
SeqList<T>::SeqList()
{
length=0;
}
template<class T>
SeqList<T>::SeqList(T a[],int n)
{
if(n>Maxsize)
cout<<"上溢"<<endl;
for(int i=0;i<n;i++)
{
data[i]=a[i];
}
length=n;
}
template<class T>
void SeqList<T>::Insert(int i,T x)
{
int j;
if(length>=Maxsize)
cout<<"上溢"<<endl;
if(i<1 || i>length+1)
cout<<"位置"<<endl;
for(j=length; j>=i; j--)
data[j]=data[j-1];
data[i-1]=x;
length++;
}
template <class T>
T SeqList<T>::Delete(int i){
int j;
T x;
if(length==0)
cout<<"下溢"<<endl;
if(i<1 || i>length)
cout<<"位置"<<endl;
x=data[i-1];
for (j=i; j<length; j++)
data[j-1]=data[j];
length--;
return x;
}
template<class T>
void SeqList<T>::PrintList()
{
for(int i=0;i<length;i++)
{
cout<<data[i]<<" ";
}
cout<<endl;
}
template<class T>
int SeqList<T>::Weizhi(int x)
{
int m=0;
for(int i=0;i<length;i++)
{
if(data[i]==x)
{
m=i+1;
break;
}
}
return m;
}
顺序表的优点是:
(1) 无需为表示结点间的逻辑关系而增加额外的存储空间(因为逻辑上相邻的元素其存储的物理位置也是相邻的);
(2) 可方便地随机存取表中的任一元素。
缺点:
(1)插入或删除运算不方便,除表尾的位置外,在表的其它位置上进行插入或删除操作都必须移动大量的结点,其效率较低;
(2) 由于顺序表要求占用连续的存储空间,存储分配只能预先进行静态分配,因此当表长变化较大时,难以确定合适的存储规模.
单链表
链式存储分配的特点:根据线性表的长度动态的申请存储空间,以解决顺序存储中存在的存储空间难以确定的问题。其实就是,每当有新的元素加入,就会创建一个节点将元素放入其中,然后用指针将新节点与旧节点连接起来。
链式存储结构的实现:单链表,双向链表,循环链表等
单链表是由一个个结点连接形成,
单链表结点结构
//在C++中,可以用结构类型来描述单链表的结点 ,由于结点的元素类型不确定,所以采用C++的模板机制。
template <typename T>
struct Node
{
T data;
Node<T> *next;
};
data为数据域,存放数据元素;next为指针域,存放该结点的后继结点的地址。
单链表的实现
#include<iostream>
using namespace std;
template<typename T>
struct Node//结点
{
T data;
Node<T> *next;
};
template<class T>
class LinkList
{
public:
LinkList()//构造空表
{
first=new Node<T>;
first->next=NULL;
}
LinkList(T a[],int n);//根据数组a和元素个数n构件非空单链表(利用头插法)
LinkList(T a[],int n,int w);//根据数组a和元素个数n构建非空单链表(利用尾插法)
~LinkList();//析构函数
void PrintList();//输出所有的元素值
void Insert(int i, T x);//根据位置i插入数据x
T Deletez(int i);//根据值i删除i所在的结点
T Deletew(int m);//根据位置m删除m位置处的结点
private:
Node<T> *first;//头指针,指向头结点
};
template<class T>
LinkList<T>::LinkList(T a[],int n)
{
first=new Node<T>;
first->next=NULL;
Node<T> *s;
for(int i=0;i<n;i++)
{
s=new Node<T>;
s->data=a[i];
s->next=first->next;
first->next=s;
}
}
template<class T>
LinkList<T>::LinkList(T a[],int n,int w)
{
Node<T> *r,*s;
first=new Node<T>;
r=first;
for(int i=0;i<n;i++)
{
s=new Node<T>;
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
}
template<class T>
void LinkList<T>::PrintList()
{
Node<T> *p;
p=first->next;
while(p)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
template <class T>
void LinkList<T>::Insert(int i, T x){
Node<T> *p; int j;
p=first ; j=0; //工作指针p初始化
while (p && j<i-1) {
p=p->next; //工作指针p后移
j++;
}
if (!p)
cout<<"位置"<<endl;
else {
Node<T> *s;
s=new Node<T>;
s->data=x; //向内存申请一个结点s,其数据域为x
s->next=p->next; //将结点s插入到结点p之后
p->next=s;
}
}
template<class T>
T LinkList<T>::Deletez(int i)
{
Node<T> *p=first,*q=NULL;
q=p->next;
int a=0;
while(q!=NULL)
{
if(q->data==i)
{
p->next=q->next;
delete q;
a=1;
PrintList();
break;
}
p=q;
q=q->next;
}
if(a==0)
cout<<"Error"<<endl;
}
template<class T>
T LinkList<T>::Deletew(int i)
{
if(i<1)
cout<<"Error"<<endl;
else
{
T x;
Node<T> *p=first,*q=NULL;
int count=0;
while(p!=NULL&&count<i-1)
{
p=p->next;
count++;
}
if(p==NULL||p->next==NULL)
cout<<"Error"<<endl;
else
{
q=p->next;
x=q->data;
p->next=q->next;
delete q;
PrintList();
}
}
}
template<class T>
LinkList<T>::~LinkList()
{
Node<T> *q;
while(first)
{
q=first->next;
delete first;
first=q;
}
}
int main()
{
int a[1000];
int b[1000];
int x;
int s;
int n=0;
int m=0;
while(cin>>x)
{
if(x==0)
break;
a[n]=x;
n++;
}
while(cin>>s)
{
if(s==0)
break;
b[m]=s;
m++;
}
int y;
cin>>y;
int z;
cin>>z;
LinkList<int> list1(a,n,0);//尾插法构建
list1.PrintList();//遍历输出
LinkList<int> list2(b,m);//头插法构建
list2.PrintList();//遍历输出
list1.Deletez(y);//按值删除
list1.Deletew(z);//按位删除
list1.~LinkList();//析构
list2.~LinkList();//析构
return 0;
}