C++实现双链表的基本功能
- 作者: 芊芊前男友就是我
- 来源: 51数据库
- 2021-08-31
双链表:在单链表的每个结点中,再设置一个指向其前驱结点的指针域
线性表的双向链表存储结构:
typedef struct node
{
datatype _data;
struct node *_next;
struct node *_front;
}node;
通过双链表的存储结构我们发现双链表可以反向查找结点优于单链表 ,实质上双链表就是以空间换取时间,虽然双链表具有可以反向查找数据的优点但是它也存在缺点:在插入和删除一个结点时需要维护两个指针变量,特别是在双链表的插入中指针的指向顺序是不可修改的。
双链表的插入过程:

双链表的删除过程:

c++实现双链表的基本功能:
typedef int datatype;
class linklist;
class node
{
friend linklist;
friend ostream &operator<<(ostream &os,node &n);
friend ostream& operator<<(ostream &os,linklist &list);
public:
node(datatype x)
:_data(x)
,_next(null)
,_front(null)
{}
private:
datatype _data;
node *_next;
node *_front;
};
ostream &operator<<(ostream &os,node &n)
{
os<_data);
if(_tail)
{
_tail->_next=tmp;
tmp->_front=_tail;
_tail=tmp;
}
else //空链表
{
_head=tmp;
_tail=tmp;
}
cur=cur->_next;
}
}
~linklist()
{
node *cur=_head;
while(cur)
{
node *del=cur;
cur=cur->_next;
delete del;
del=null;
}
}
public:
void pushback(datatype x)
{
node *newnode=new node(x);
if(_tail)
{
_tail->_next=newnode;
newnode->_front=_tail;
_tail=newnode;
}
else
{
_head=newnode;
_tail=newnode;
}
}
void popback()
{
if(!_head && !_tail) //空链表
{
cout<<"链表已空不可尾删"<_front;
_tail->_next=null;
delete tmp;
tmp=null;
}
}
void pushfront(datatype x)
{
node *newnode=new node(x);
if(_head)
{
node *tmp=_head;
newnode->_next=tmp;
tmp->_front=newnode;
}
else
{
_tail=newnode;
}
_head=newnode; //更新头
}
void popfront()
{
if(!_head && !_tail) //空链表
{
cout<<"链表已空不可头删"<_next;
_head->_front=null;
delete del;
del=null;
}
}
node *findnum(datatype x)
{
node *cur=_head;
while(cur)
{
if(cur->_data == x)
return cur;
cur=cur->_next;
}
return null;
}
void insert(node *pos,datatype x) //在指定位置后插
{
node *newnode=new node(x);
if(pos->_next)
{
newnode->_front=pos;
newnode->_next=pos->_next;
pos->_next->_front=newnode;
pos->_next=newnode;
}
else //在最后一个结点后插,类似pushback
{
pos->_next=newnode;
newnode->_front=pos;
_tail=newnode; //更新尾
}
}
void insert(int,node *pos,datatype x) //在指定位置前插
{
node *newnode=new node(x);
if(pos->_front)
{
newnode->_next=pos;
pos->_front->_next=newnode;
newnode->_front=pos->_front;
pos->_front=newnode;
}
else //在第一个结点的前插,类似pushfront
{
newnode->_next=pos;
pos->_front=newnode;
_head=newnode; //更新头
}
}
void remove(datatype &x)
{
node *pos=this->findnum(x);
if(pos != null)
{
if((!(pos->_front)) && pos->_next) //删除第一个结点
{
node *tmp=pos->_next;
tmp->_front=null;
_head=tmp;
}
else if(pos->_front && (!(pos->_next))) //删除最后一个结点
{
node *tmp=pos->_front;
tmp->_next=null;
_tail=tmp;
}
else //删除中间节点
{
node *front=pos->_front;
node *next=pos->_next;
next->_front=front;
front->_next=next;
}
delete pos;
pos=null;
}
}
void removeall(datatype &x)
{
node *cur=_head;
node *ret=this->findnum(x);
if(ret != _head) //可删除第一个结点不是要删除的元素
{
while(cur)
{
remove(x);
cur=cur->_next;
}
}
}
void sort()
{
int flag=1;
node *cur=_head;
node *tail=null;
while(cur != tail)
{
while(cur->_next != tail)
{
if(cur->_data > cur->_next->_data)
{
datatype tmp=cur->_data;
cur->_data=cur->_next->_data;
cur->_next->_data=tmp;
flag=0;
}
cur=cur->_next;
}
if(flag == 1)
break;
tail=cur;
cur=_head;
}
}
void erase(node *pos)
{
if((!(pos->_front)) && pos->_next) //删除第一个结点
{
node *tmp=pos->_next;
tmp->_front=null;
_head=tmp;
}
else if(pos->_front && (!(pos->_next))) //删除最后一个结点
{
node *tmp=pos->_front;
tmp->_next=null;
_tail=tmp;
}
else //删除中间节点
{
node *front=pos->_front;
node *next=pos->_next;
next->_front=front;
front->_next=next;
}
delete pos;
pos=null;
}
private:
node *_head;
node *_tail;
};
ostream& operator<<(ostream &os,linklist &list)
{
node *cur=list._head;
while(cur)
{
os<<(*cur)<<" ";
cur=cur->_next;
}
return os;
}
在c++实现中如果遇到结点结构最好定义为struct,否则就会像上述情况一样需要声明多次友元,反而破坏了类的封装性
测试代码:
void menu()
{
cout<<"************1.尾插************2.尾删**************"<
over
推荐阅读
