【C++】模板实现带头节点的双向循环链表
来源:互联网 发布:matlab编程第二版.pdf 编辑:程序博客网 时间:2024/04/28 10:20
链表分为带头节点和不带头节点,单链表和双向循环链表。
带头节点的链表虽然有头结点,但是并不存储数据,双向循环链有指向前一个数的指针和指向后一个数的指针。
如下图:
先来实现一些主要的函数:
List的构造函数和析构函数:
List(){_head = new Node;_head->_next = _head;_head->_prev = _head;}~List(){clear();delete _head;_head = NULL;}
List在任意一个位置插入一个数和删除一个数
//任意一个位置插入一个数,在pos的前面插入一个数据void Insert(Node* pos, const T& x){assert(pos);Node* tmp = new Node(x);Node* cur = pos;Node* prev = cur->_prev;prev->_next = tmp;tmp->_prev = prev;tmp->_next = cur;cur->_prev = tmp;}//删除任意一个位置的数void Erase(Node* pos){assert(pos && pos != _head);Node* prev = pos->_prev;Node* next = pos->_next;prev->_next = next;next->_prev = prev;delete pos;}
有了插入和删除函数之后,其他的函数都可以用Erase和Insert来复用:
尾部插入和删除函数:
//尾部插入一个数void PushBack(const T& x){Insert(_head, x);}//尾部删除一个数void PopBack(const T& x){Erase(_head->_prev);}
头部插入和删除数据:
//头部插入一个数void PushFront(const T& x){Insert(_head->_next,x);}//头部删除一个数void PopFront(const T& x){Erase(_head->_next);}
构造函数和赋值运算符重载:
//拷贝构造函数List(const List<T> & l){_head = new Node();_head->_next = _head;_head->_prev = _head;Node* cur = (l._head)->_next;while (cur != l._head){this->PushBack(cur->_data);cur = cur->_next;}}//赋值运算符重载List<T>& operator=(const List<T>& l){if (this != &l){this->clear();Node* cur = l._head->_next;while (cur != l._head){this->PushBack(cur->_data);cur = cur->_next;}}return *this;}
在插入和删除数据的时候要考虑双向链表里面会出现的各种情况!
以下是完整的代码:
ListNode.h#pragma once#include<assert.h>template<class T>struct ListNode{T _data;ListNode<T>* _next;ListNode<T>* _prev;ListNode(const T& x = T()):_data(x), _next(NULL), _prev(NULL){}};template<class T>class List{typedef ListNode<T> Node;public:List(){_head = new Node;_head->_next = _head;_head->_prev = _head;}~List(){clear();delete _head;_head = NULL;}//删除任意一个位置的数void Erase(Node* pos){assert(pos && pos != _head);Node* prev = pos->_prev;Node* next = pos->_next;prev->_next = next;next->_prev = prev;delete pos;}//任意一个位置插入一个数,在pos的前面插入一个数据void Insert(Node* pos, const T& x){assert(pos);Node* tmp = new Node(x);Node* cur = pos;Node* prev = cur->_prev;prev->_next = tmp;tmp->_prev = prev;tmp->_next = cur;cur->_prev = tmp;}//尾部插入一个数void PushBack(const T& x){Insert(_head, x);}//尾部删除一个数void PopBack(const T& x){Erase(_head->_prev);}//头部插入一个数void PushFront(const T& x){Insert(_head->_next,x);}//头部删除一个数void PopFront(const T& x){Erase(_head->_next);}//查找一个数void Find(const T& x){Node* cur = _head->_next;while (cur != _head){if (cur->_data == x){return cur;}return NULL;}}//清除void clear(){Node* cur = _head->_next;while (cur != _head){Node* next = cur->_next;delete cur;cur = next;}_head->_next = _head;_head->_prev = _head;}//打印void Print(){Node* cur = _head->_next;while (cur!=_head){cout << cur->_data << "";cur = cur->_next;}cout << endl;}//拷贝构造函数List(const List<T> & l){_head = new Node();_head->_next = _head;_head->_prev = _head;Node* cur = (l._head)->_next;while (cur != l._head){this->PushBack(cur->_data);cur = cur->_next;}}//赋值运算符重载List<T>& operator=(const List<T>& l){if (this != &l){this->clear();Node* cur = l._head->_next;while (cur != l._head){this->PushBack(cur->_data);cur = cur->_next;}}return *this;}protected:Node* _head;};void Test1()//尾部插入和删除{//插入List<int> l;l.PushBack(1);l.Print();l.PushBack(2);l.Print();l.PushBack(3);l.Print();l.PushBack(4);l.Print();//删除l.PopBack(1);l.Print();l.PopBack(1);l.Print();l.PopBack(1);l.Print();}void Test2()//头部插入和删除{//插入List<int> l;l.PushFront(1);l.Print();l.PushFront(2);l.Print();l.PushFront(3);l.Print();//删除l.PopFront(1);l.Print();l.PopFront(1);l.Print(); l.PopFront(1);l.Print(); }测试函数Test.cpp#include<iostream>using namespace std;#include"ListNode.h"int main(){Test1();Test2();system("pause");return 0;}
0 0
- 【C++】模板实现带头节点的双向循环链表
- C语言实现双向非循环链表(不带头结点)的节点插入
- C语言实现双向非循环链表(带头结点尾结点)的节点插入
- 双向循环带头节点链表
- 不带头节点的双向循环链表基本操作
- 数据结构示例之带头节点的双向循环链表
- 数据结构示例之带头节点的双向循环链表
- 如何创建不带头节点的双向循环链表
- 用模板实现顺序表和带头结点的双向循环链表
- C-[双向循环带头链表]-代码
- C语言实现双向非循环链表(不带头结点)的基本操作
- C语言实现双向非循环链表(不带头结点)的逆序打印
- C语言实现双向非循环链表(不带头结点)的清空
- C语言实现双向非循环链表(带头结点尾结点)的基本操作
- 带头结点的双向循环链表
- 带头结点的双向循环链表
- 带头结点的双向循环链表
- 不带头节点的双向循环链表的基本操作
- C# js select给选中的项加上selected
- 全局改变所有Activity的背景
- LEETCODE--Number of Segments in a String
- CSDN日报20170220——《从安卓调整到服务端后的思考》
- 官方Tomcat 8.0.24 Web漏洞整改记录
- 【C++】模板实现带头节点的双向循环链表
- UML类图新手入门级介绍
- 1114. Family Property (25)
- 你的生命,我曾经如此焦灼过
- android应用开发-从设计到实现 1-2 功能的确定
- 实现滑动选择价格区间的自定义seekbar
- 近乎完美的金额正则表达式两位小数
- POST和PUT的区别
- selenium+Python 非select下拉菜单定位