C++---实现简单的带头循环双向链表

C++实现简单的带头循环双向链表

list
   带头双向循环链表听着感觉好像很难的样子,其实,它的实现相对比较简单,它的前驱结点与后继结点都已知,也不需要再遍历得到指针。
   在构造链表的时候,记得要初始化头结点。还有在操作前后指针的时候,要记得将指针保存好,得理清楚这几个结点的关系,不然就会导致有些结点丢失。
List.cpp

#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

typedef int DataType; 
struct ListNode 
{ 
    ListNode* _next; 
    ListNode* _prev; 
    DataType _data;
    ListNode(DataType x) 
        :_next(NULL) 
         ,_prev(NULL) 
         ,_data(x) 
    {} 
}; 
//带头双链表
class List 
{ 
    typedef ListNode Node; 
public: 
    List() 
        :_head(new Node(DataType())) 
    { 
        _head->_next = _head; 
        _head->_prev = _head; 
    } 

    List(const List& l)
        :_head(new Node(DataType())) 
    { 
       _head->_next = _head; 
       _head->_prev = _head; 
       Node *cur =l._head->_next;
       Node *prev = NULL;
       Node *tmp = _head;
       while(cur != l._head)
       {
           prev = tmp;
           tmp = new Node(cur->_data);
           tmp->_prev = prev;
           prev->_next = tmp;
           cur=cur->_next;
       }
       tmp->_next = _head;
       _head->_prev = tmp;
    } 
List& operator=(List l)
{
    Node *tmp = _head;
    _head = l._head;
    l._head = tmp;
    return *this;
}
~List()
{
    Node *tmp = _head->_next;
    while(tmp != _head)
    {
        Node *cur = tmp->_next;
        delete tmp;
        tmp = cur;
    }
}
//尾插
void PushBack(DataType x)
{
// 当写了Insert之后,就可以直接使用insert函数来进行插入,不需要再自己实现
//    Node *tmp = _head->_prev;
//    Node *newnode = new Node(x);
//    tmp->_next = newnode;
//    newnode->_prev = tmp;
//    newnode->_next = _head;
//    _head->_prev = newnode;
    Insert(_head->_prev,x);
}
//头插
void PushFront(DataType x)
{
//    Node *newnode = new Node(x);
//   newnode->_next = _head->_next;
//   _head->_next = newnode;
//   newnode->_prev = _head;
//   newnode->_next->_prev = newnode;
   Insert(_head->_next,x);
}
//尾删
void PopBack()
{
// 可以复用下面写的Erase函数,可以在任意位置删除。
//    Node *cur = _head->_prev;
//    cur->_prev->_next = _head;
//    _head->_prev = cur->_prev;
//    delete cur;
    Erase(_head->_prev);
}
//头删
void PopFront()
{
//    if(_head->_next==_head)
//        return;
//    Node *tmp = _head->_next->_next;
//    delete _head->_next;
//    _head->_next = tmp;
//    tmp->_prev = _head;
    Erase(_head->_next);
}
Node* Find(DataType x)
{
    if(_head->_next == _head)
        return NULL;
    Node *cur = _head->_next;
    while(cur != _head)
    {
        if(cur->_data == x)
            return cur;
        cur=cur->_next;
    }
    return NULL;
}
void Insert(Node* pos, DataType x)
{
    Node *newnode = new Node(x);
    newnode->_next = pos;
    pos->_prev->_next = newnode;
    newnode->_prev = pos->_prev;
    pos->_prev = newnode;
}
void Erase(Node* pos)
{
    Node *next = pos->_next;
    Node *prev = pos->_prev;
    delete pos;
    next->_prev = prev;
    prev->_next = next;
}
void Print()
{
    Node *tmp = _head->_next;
    while(tmp != _head)
    {
        printf("[%d] ",tmp->_data);
        tmp = tmp->_next;
    }
    printf("\n");
}
private: 
Node* _head; 
}; 
int main()
{
    List l;
    l.PushFront(1);
    l.PushBack(2);
    l.PushBack(3);
    l.PushBack(4);
    l.PushBack(5);
    l.PushBack(6);
    List l1;
    l1=l;
    l.Print();
    l1.Print();
    l.PushFront(0);
    l.Print();
    l.PopBack();
    l.Print();
    l.PopFront();
    l.Print();
    ListNode *ret = l.Find(3);
    cout<<ret->_data<<endl;
    cout<<ret->_next->_data<<endl;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
约瑟夫问题是经典的数学游戏,也称为约瑟夫环,由于其富有趣味性和一定的数学难度而被广泛研究和应用。解决约瑟夫问题的方法有多种,其中一种常用方法是使用双向循环链表带头结点。 双向循环链表是一种特殊的链表,它可以遍历整个链表,即尾节点的下一个结点是头结点,头结点的上一个结点是尾节点,这样形成的链表称为双向循环链表带头结点的双向循环链表在头结点前面加入一个空结点,使得空结点也能对链表中结点进行操作。 在解决约瑟夫问题时,我们首先需要初始化双向循环链表,然后按照一定规则进行出队操作,直到只剩下最后一个结点为止。假设约瑟夫问题中有n个人围成一圈,从第k个人开始报数,报到第m个人就将其出队,然后从下一个人重新开始报数,求最后留下的人的编号。 具体实现时,我们可以根据输入的n和k创建双向循环链表,并从头结点开始依次插入n个结点,然后设置m的值并从头结点开始不断遍历链表直到只剩下一个结点。在遍历过程中,每经过m个结点就将该结点从链表中删除,并将该结点的下一个结点作为新的起点继续报数。最后剩下的那个结点即为答案。 总之,使用双向循环链表带头结点解决约瑟夫问题可以简化求解过程,提高代码效率和可读性,是一种比较常用的数据结构和算法应用方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值