template <class elemType>//由于不知道实际的元素是什么类型,所以将其作为类模板参数
class list {
public:
// 清除
virtual void clear() = 0;
// 长度
virtual int length() const = 0;
// 插入
virtual void insert(int i, const elemType &x) = 0;
// 删除
virtual void remove(int i) = 0;
// 搜索
virtual int search(const elemType &x) const = 0;
// 访问
virtual elemType visit(int i) const = 0;
// 遍历
virtual void traverse() const = 0;
// 析构
virtual ~list() {};
};
template <class elemType>
class seqList: public list<elemType> {
private:
elemType *data;
int currentLength;
int maxSize;
// 为了解决插入元素时,数组容量不够的问题
void doubleSpace();
public:
seqList( int initSize = 10 );
// 析构函数:还掉动态空间
~seqList( ) { delete [] data; }
// 清空数组元素:只要把表长设为0
void clear( ) { currentLength = 0; }
// 数组长度:只需要返回这个私有成员变量currentLength
int length( ) const { return currentLength; }//此处const表示这个函数不会对数组的值进行修改
void insert( int i, const elemType &x); //此处const表示这个函数对x进行修改
void remove( int i );
int search( const elemType &x ) const ;
// 访问数组元素:返回下标为i的数组元素
elemType visit( int i) const { return data[i] ; }
void traverse( ) const ;
};
template <class elemType>
seqList<elemType>::seqList(int initSize) {
data = new elemType[initSize];
maxSize = initSize;
currentLength = 0;
}
template <class elemType>
int seqList<elemType>::search (const elemType &x) const {
int i;
// 空循环,不满足循环条件时跳出
for (i = 0; i < currentLength && data[i] != x; ++i) ;
if (i == currentLength)
return -1;
else return i;
}
template <class elemType>
void seqList<elemType>::traverse() const {
cout << endl;
for (int i = 0; i < currentLength; ++i)
cout << data[i] << ' ';
}
template <class elemType>
void seqList<elemType>::insert(int i, const elemType &x) {
// 如果数组放满了,先扩大数组空间
if (currentLength == maxSize)
doubleSpace();
// 从后往前,元素后移
for ( int j = currentLength; j > i; j--)
data[j] = data[j-1];
// 空出空间,插入元素,表长加1
data[i] = x;
++currentLength;
}
template <class elemType>
void seqList<elemType>::doubleSpace() {
//实现功能:将容量扩大两倍,并保留有原本的数据
// 保存指向原来空间的指针
elemType *tmp = data;
// 重新申请空间
maxSize *= 2;
data = new elemType[maxSize];
// 拷贝原有数据
for (int i = 0; i < currentLength; ++i)
data[i] = tmp[i];
// 清除原来申请的空间
delete [] tmp;
}
template <class elemType>
void seqList<elemType>::remove(int i) {
// 后面所有元素前移,表长减1
for (int j = i; j < currentLength - 1; j++)
data[j] = data[j+1] ;
--currentLength;
}
template <class elemType>
class sLinkList: public list<elemType> {
private:
// 定义一个结点的结构体,里面的所有成员都是公有的
//虽然成员是公有的,但是node在单链表类的私有成员里,所以用户根本看不到,而链表的操作可以看到单链表类的私有成员,可以操作node的公有成员
//class定义,没有声明的情况下成员都为私有;
//struct定义,没有声明的情况下成员都为公有
struct node {
elemType data;
node *next;
node(const elemType &x, node *n = NULL) { data = x; next = n; }
node( ):next(NULL) { }//缺省情况下的构造函数
~node() {};
};
node *head;
int currentLength;//保存链表长度,否则想要获取长度需要遍历整个链表
node *move(int i) const; //操作过程中常常要移动指针指向第i个元素,所以将其设计为一个私有的辅助的工具函数
public:
// 构造函数:创建空的单链表
sLinkList() {
head = new node;
currentLength = 0;
}
// 析构函数:调用clear把单链表的所有结点都还掉,再把头结点还掉
~sLinkList() { clear(); delete head; }
void clear() ;
// 表的长度:返回私有的成员变量
int length() const { return currentLength; }
void insert(int i, const elemType &x);
void remove(int i);
int search(const elemType &x) const ;
elemType visit(int i) const;
void traverse() const ;
};
template <class elemType>
void sLinkList<elemType>::clear() {
node *p = head->next, *q;
head->next = NULL;
// 只要p不是空的,把p的下一个结点记下来,删掉p,再把q赋给p
while (p != NULL) {
q = p->next;
delete p;
p=q;
}
currentLength = 0;
}
template <class elemType>
void sLinkList<elemType>::insert(int i, const elemType &x) {
node *pos;
// 通过move函数找到第i-1个元素的地址
pos = move(i - 1);
pos->next = new node(x, pos->next);
++currentLength;
}
template <class elemType>
sLinkList<elemType>::node * sLinkList<elemType>::move(int i) const {
node *p = head;
while (i-- >= 0) p = p->next;
return p;
}
template <class elemType>
void sLinkList<elemType>::remove(int i) {
node *pos, *delp;
// 通过move函数找到第i-1个元素的地址
pos = move(i - 1);
// 找到被删结点的位置,让第i-1个元素的后继指针指向第i+1个结点
delp = pos->next;
pos->next = delp->next;
// 释放被删结点的空间
delete delp;
--currentLength;
}
template <class elemType>
int sLinkList<elemType>::search(const elemType &x) const {
// 指针指向第一个元素A_0
node *p = head->next;
int i = 0;
while (p != NULL && p->data != x) {
p = p->next;
++i;
}
// p为NULL表示找到表尾都没有找到
if (p == NULL)
return -1;
else
return i;
}
template <class elemType>
elemType sLinkList<elemType>::visit(int i) const {
return move(i)->data;
}
template <class elemType>
void sLinkList<elemType>::traverse() const {
node *p = head->next;
cout << endl;
while (p != NULL) {
cout << p->data << " ";
p=p->next;
}
cout << endl;
}
template <class elemType>
class dLinkList: public list<elemType> {
private:
struct node {
elemType data;
node *prev, *next;
node(const elemType &x, node *p = NULL, node *n = NULL) { data = x; next = n; prev = p; }
node( ):next(NULL), prev(NULL) {}
~node() {}
};
node *head, *tail;
int currentLength;
node *move(int i) const;
public:
dLinkList();
// 析构函数:先调用clear删除所有元素,再删除头尾结点
~dLinkList() {
clear();
delete head;
delete tail;
}
void clear();
// 返回元素数量
int length() const { return currentLength; }
void insert(int i, const elemType &x);
void remove(int i);
int search(const elemType &x) const;
elemType visit(int i) const;
void traverse() const;
};
template <class elemType>
dLinkList<elemType>::dLinkList() {
head = new node;
head->next = tail = new node;
tail->prev = head;
currentLength = 0;
}
template <class elemType>
void dLinkList<elemType>::insert(int i, const elemType &x) {
node *pos, *tmp;
pos = move(i);
tmp = new node(x, pos->prev, pos);
pos->prev->next = tmp;
pos->prev = tmp;
++currentLength;
}
template <class elemType>
void dLinkList<elemType>::remove(int i) {
node *pos;
pos = move(i);
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
delete pos;
--currentLength;
}
其他操作:双链表其他操作和单链表基本相同。
例题
一个学校里老师要将班上N个同学排成一列,同学被编号为1∼N,他采取如下的方法:
先将1号同学安排进队列,这时队列中只有他一个人;
2−N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1 ~ (i-1)中某位同学(即之前已经入列的同学)的左边或右边;
从队列中去掉M (M在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。 输入描述:
第1行为一个正整数N,表示了有N个同学。
第2−N行,第i行包含两个整数k p,其中k为小于i的正整数,p为0或者1。若p为0,则表示将i号同学插入到k号同学的左边,p为1则表示插入到右边。
第N+1行为一个正整数M,表示去掉的同学数目。
接下来M行,每行一个正整数x,表示将x号同学从队列中移去,如果x号同学已经不在队列中则忽略这一条指令。
输出描述:
一行,包含最多N个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。
示例 1:
输入:
4
1 0
2 1
1 0
2
3
3
输出:
2 4 1
#include
#include
#include
#include
#define N 100005
using namespace std;
struct node {
int l, r;
}nod[N];
int head, tail;
void add(int a, int b, int c) {
nod[a].r = b;
nod[b].r = c;
nod[c].l = b;
nod[b].l = a;
}
void del(int a, int b, int c) {
nod[a].r = c;
nod[c].l = a;
nod[b].r = nod[b].l = 0;
}
int n, m;
int main() {
scanf("%d", &n);
head = n + 1;
tail = n + 2;
nod[head].r = tail;
nod[tail].l = head;
add(head, 1, tail);
for (int i = 2; i <= n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
if (!y) add(nod[x].l, i, x);
else add(x, i, nod[x].r);
}
scanf("%d", &m);
for (int i = 0; i < m; ++i) {
int x;
scanf("%d", &x);
if (!nod[x].l) continue;
del(nod[x].l, x, nod[x].r);
}
for (int i = nod[head].r; i != tail; i = nod[i].r) printf("%d ", i);
return 0;
}
```