【C++】 双向链表.cpp
2016-03-05 16:54
351 查看
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
一般我们都构造双向循环链表,因为双向链表解决了单向链表的不足和问题,而单链表因为出现的问题多,所以在面试中经常会考到单链表的问题。
在这里,我用 .cpp对双向链表的基本操作进行实现。
具体代码如下:
List.h文件:
本文出自 “Vs吕小布” 博客,谢绝转载!
一般我们都构造双向循环链表,因为双向链表解决了单向链表的不足和问题,而单链表因为出现的问题多,所以在面试中经常会考到单链表的问题。
在这里,我用 .cpp对双向链表的基本操作进行实现。
具体代码如下:
List.h文件:
#pragma once typedef int DataType; struct ListNode //全部用作公有的就定义为struct,用作私有就定义class { //当然用class,写在public中也可以 DataType _data; ListNode* _next; //前驱指针 ListNode* _prev; //后继指针 ListNode(DataType x) //构造函数 :_data(x) ,_next(NULL) ,_prev(NULL) {} }; class List { public: List() :_head(NULL) ,_tail(NULL) {} ~List() { Clear(); } public: void PushBack(DataType x) { if(_head == NULL) { _head = _tail = new ListNode(x);//调用构造函数 } else { ListNode* tmp = new ListNode(x); _tail->_next = tmp; tmp->_prev = _tail; _tail = tmp; } } void PopBack() { //没有节点 //一个节点 //一个以上节点 if(_head == NULL) { return; } else if(_head == _tail) { delete _head; _head = _tail = NULL; } else { ListNode* cur = _tail->_prev; delete _tail; _tail = cur; cur->_next = NULL; } } void PushFront(DataType x) { if(_head == NULL) { _head = _tail = new ListNode(x); } else { ListNode* tmp = new ListNode(x); tmp->_next = _head; _head = tmp; } } void PopFront() { if(_head == NULL)//空 { return; } else if(_head == _tail)//一个节点 { delete _head; _head = _tail = NULL; } else //一个以上节点 { ListNode* del = _head; _head = _head->_next; _head->_prev = NULL; delete del; } } void Insert(ListNode* pos,DataType x) { assert(pos); if(pos == _tail) { PushBack(x); } else { /* ListNode* tmp = new ListNode(x); tmp->_next = pos->_next; pos->_next->_prev = tmp; //使用这种两个指针的方式虽然可以达到目的,但是容易出现问题 pos->_next = tmp; //首先得考虑pos是否为空,其次若pos->_next为空,再想找到它的prev就会出错 tmp->_prev = pos; */ ListNode* tmp = new ListNode(x);//这样定义两个指针保存前后的节点,就不容易出错 ListNode* next = pos->_next; tmp->_next = next; next->_prev = tmp; pos->_next = tmp; tmp->_prev = pos; } } ListNode* Find(DataType x) { if(_head == NULL) { return NULL;//找不到返回空 } else { ListNode* cur = _head; while(cur) { if(cur->_data == x) { return cur; } cur = cur->_next; } } } void Erase(ListNode* pos) { assert(_head); assert(pos); if(pos == _head)//删除头节点 { PopFront(); /* ListNode* del = _head; _head = _head->_next; _head->_prev = NULL; delete del; */ } else if(pos == _tail)//删除尾节点 { PopBack(); } else // 删除非头尾节点 { /* ListNode* cur = pos->_prev; cur->_next = pos->_next; pos->_next->_prev = cur; delete pos; */ ListNode* prev = pos->_prev; ListNode* next = pos->_next; prev->_next = next; next->_prev = prev; delete pos; } } void PrintList()//在此用不上前驱节点prev { ListNode* cur = _head; while(cur) { cout<<cur->_data<<"->"; cur = cur->_next; } cout<<"NULL"<<endl; } void Clear() { ListNode* cur = _head; while(cur) { ListNode* del = cur; cur = cur->_next; delete del; } } //翻转双向链表 void reverse() { /* ①.交换值 ListNode* begin = _head; ListNode* end = _tail; while(begin != end && begin->_prev != end)//当两个指针相遇或者已经偏离停止 { swap(begin->_data , end->_data); begin = begin->_next; end = end ->_prev; } */ //②.交换指针 ListNode* cur = _head; while(cur) { swap(cur->_prev , cur->_next);//把每个节点的前后指针交换 cur = cur->_prev; } swap(_head,_tail); } private: ListNode* _head; ListNode* _tail; }; void Test() { List l; l.PushBack(1); l.PushBack(2); l.PushBack(3); l.PushBack(4); l.PushBack(5); l.PrintList(); l.PopBack(); l.PrintList(); l.PushFront(0); l.PrintList(); l.PopFront(); l.PrintList(); l.Insert(l.Find(1),0); l.PrintList(); l.Erase(l.Find(1)); l.PrintList(); l.reverse(); l.PrintList(); }List.cpp 文件:(测试)
#include<iostream> #include<assert.h> using namespace std; #include "DoubleSList.h" //双向链表 int main() { Test(); return 0; }我们发现,当遇到问题时不能直接上手去写,为什么?因为我们写的是代码,而不是bug,正确的程序是需要严谨的逻辑为前提,所以在写代码之前需要谨慎的思考各种临界的情况和异常,这是非常之重要的!
本文出自 “Vs吕小布” 博客,谢绝转载!
相关文章推荐
- C++ STL <map> 用法简介
- 2016年的C++常见的面试问题详解~搬至牛客网~2
- 一起talk C栗子吧(第二十回:C语言实例--括号匹配)
- 二维数组中的查找
- 橱窗布置c++动态规划
- c++ 学习笔记之动态内存管理
- C++设计模式总结
- C++ string类实现
- c++ 函数的递归调用
- c++ primer plus 第十七章 输入 输出 文件 IO iostream fstream
- c++ 广义表
- Bill学C++ 第三季:求余运算符+运算符结合律
- c\c++中的形参与实参
- C++ 函数的嵌套调用
- c++ const 关键字
- c语言:输入10个数,输出值最大的元素和该数是第几个数。(数组元素作函数实参)
- 2016年的C++常见的面试问题详解~搬至牛客网~strcpy
- C++二分查找法
- 数组写入Txt 与读Txt到数组 C++
- switch语句解析