尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

采用哨兵节点的C++双链表实现

采用哨兵节点的C++双链表实现
📅 发布时间:2026/7/7 13:52:48

#include<iostream>

#include<string>

#include<stdexcept>

using namespace std;

template<typename E>

class Dlist{

struct Node{

E val;

Node *next;//后驱

Node *prev;//前驱

Node(const E& value):val(value),next(nullptr),prev(nullptr){}

};

Node *head;//哨兵头

Node *tail;//哨兵尾

int size;

//检查索引是否为合法的元素索引 (0,size-1)

bool isElementIndex(int index)const{

return index>=0 &&index<size;

}

//检查索引是否为合法的插入位置(0,size]

bool isPositionIndex(int index)const{

return index>=0 &&index<=size;

}

void checkElementIndex(int index)const{

if(!isElementIndex(index)){

throw out_of_range("Index: "+to_string(index)+",size"+to_string(size));

}

}

void checkPositionIndex(int index)const{

if(!isPositionIndex(index)){

throw out_of_range("Index: "+to_string(index)+",size"+to_string(size));

}

}

Node *getNode(int index)const{

if(index<size/2){ //根据索引位置决定从头找还是从尾找

Node *p=head->next; //头节点向后遍历

for(int i=0;i<index;i++){

p=p->next;

}

return p;

}

else{

Node *p=tail->prev; //尾节点向前遍历

for(int i=size-1;i>index;i--){

p=p->prev;

}

return p;

}

}public:

Dlist(){

head=new Node(E()); // 创建头哨兵

tail=new Node(E()); // 创建尾哨兵

head->next=tail; //初始状态 头指向尾 尾指向头

tail->prev=head;

size=0;

}

~Dlist(){

while(size>0){

removeFirst();

}

delete head;

delete tail;

}

void addFirst(const E& e){

Node *newNode=new Node(e);

Node *temp=head->next;//暂存第一个真实结点

temp->prev=newNode;

newNode->next=temp;

head->next=newNode;

newNode->prev=head;

size++;

}

void addLast(const E& e){

Node* newNode=new Node(e);

Node* temp=tail->prev; //暂存最后一个真实节点

temp->next=newNode;

newNode->prev=temp;

newNode->next=tail;

tail->prev=newNode;

size++;

}

void insert(int index,const E& element){

checkPositionIndex(index);

if(index==size){

addLast(element);

return ;

}

//找到前驱

Node *p=getNode(index);

Node *prev=p->prev;

Node *newNode=new Node(element);

// 将 newNode 插入到 prev 和 p 之间

p->prev=newNode;

prev->next=newNode;

newNode->prev=prev;

newNode->next=p;

size++;

}

// 获取链表当前元素个数

int size1() const{

return size;

}

// 判断链表是否为空

bool isEmpty()const{

return size==0;

}

E removeFirst(){

if(isEmpty()){

throw out_of_range("No elemnets to remove");

}

Node *x=head->next;

Node *temp=x->next;

head->next=temp;

temp->prev=head;

E val=x->val;

x->prev=nullptr;

x->next=nullptr;

delete x;

size--;

return val;

}

E removeLast(){

if(isEmpty())

throw out_of_range("No elements to remove");

Node *x=tail->prev;

Node *temp=x->prev;

tail->prev=temp;

temp->next=tail;

E val=x->val;

x->prev=nullptr;

x->next=nullptr;

delete x;

size--;

return val;

}

E remove(int index){

checkElementIndex(index);

Node *x=getNode(index); // 找到目标节点

Node *prev=x->prev;

Node *next=x->next;

// 将目标节点的前驱和后继相连 实现摘除目标节点

prev->next=next;

next->prev=prev;

E val=x->val;

x->prev=nullptr;

x->next=nullptr;

delete x;

size--;

return val;

}

// 获取第一个元素

E getFirst()const{

if(isEmpty()){

throw out_of_range("No elements in the list");

}

return head->next->val;

}

// 获取最后一个元素

E getLast()const{

if(isEmpty()){

throw out_of_range("No elements in the list");

}

return tail->prev->val;

}

// 获取指定位置的元素

E get(int index) const {

checkElementIndex(index);

Node* p = getNode(index);

return p->val;

}

// 修改指定位置的元素,并返回旧值

E set(int index,const E& element){

checkElementIndex(index);

Node *p=getNode(index);

E oldval=p->val;

p->val=element;

return oldval;

}

//打印链表内容

void print()const{

cout<<"size="<<size<<endl;

Node *p=head->next;// 从第一个真实节点开始

while(p!=tail){ // 遇到尾哨兵即停止

cout<<p->val;

if(p->next!=tail){

cout<<"<->";// 非最后一个元素时打印连接符

}

p=p->next;

}

cout<<"->null"<<endl;

}

};


int main(){

Dlist<int>list;

list.addLast(1);

list.addFirst(0);

list.addLast(2);

list.insert(2,100);

cout<<"初始链表:"<<endl;

list.print();

cout<<"removeFirst:"<<list.removeFirst()<<endl;

cout<<"removeLast:"<<list.removeLast()<<endl;

cout<<"remove(1):"<<list.remove(1)<<endl;

cout << "\n删除后链表:" << endl;

list.print();

cout<<"getFirst:"<<list.getFirst()<<endl;

cout<<"getLast:"<<list.getLast()<<endl;

cout<<"get(0)"<<list.get(0)<<endl;

cout << "\nset(0, 999) 旧值: " << list.set(0, 999) << endl;

cout<<"修改后:"<<endl;

list.print();

cout<<"\nsize:"<<list.size1()<<endl;

cout<<"isEmpty:"<<list.isEmpty()<<endl;

return 0;

}

相关新闻

  • 网易云音乐NCM格式转换技术深度解析:ncmdumpGUI如何实现数字音频文件解放
  • MAX77654与MK64FN1M0VDC12构建高效电源管理系统
  • 如何让GitHub下载速度飙升10倍:Fast-GitHub插件终极配置指南

最新新闻

  • Calibre路径翻译插件NoTrans:彻底解决中文路径乱码问题的终极指南
  • ICM-42688-P与MK64FX512VDC12在机器人控制与工业监测中的应用
  • 2026年论文党必备:盘点2026年备受追捧的的降AIGC工具
  • ICM-42688-P与MK20DN128VFM5在工业运动感知中的高效协同
  • Java计算机毕设之基于前后端分离的宠物寄养机构服务平台的设计与实现 基于 SpringBoot 的宠物寄养状态跟踪系统(完整前后端代码+说明文档+LW,调试定制等)
  • B. Crimson Triples(Codeforces 2238)

日新闻

  • Android逆向分析全能助手:集成化工具链与自动化工作流设计
  • 面搜索(Faceted Search)原理与工程实践指南
  • 神经网络调参避坑指南:从5个常见Loss曲线形态定位超参数问题

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号