双向链表(C++实现)
////////////////////////////////////////////////////////////////////////////////////// /////// 这里建立两个类,一个节点类和一个List类,与单链表不同的是双向链表的节点要多一 ////// 个前驱指针,相应的,双向链表函数实现要与单链表实现有所差异 typedef int DataType; //struct LinkNode //节点类(复合形态) //{ // friend class SList; //将SList设为友元,便于SList类可以访问节点类的私有成员 //public: // LinkNode(const DataType x); //private: // DataType _data; //节点的数据 // LinkNode* _next; //指向该节点的下一个节点 // LinkNode* _prev; //指向该节点的前一个节点 //}; //直接用struct定义LinkNode类,因为struct的成员默认为公有数据成员,所以可直接访问 struct LinkNode //节点类(建议写法) { LinkNode(const DataType x); DataType _data; //节点的数据 LinkNode* _next; //后继指针 LinkNode* _prev; //前驱指针 }; class List //链表类 { public: List(); //构造函数 List(const List& s); //拷贝构造 List &operator=(List& s); //赋值运算符的重载 ~List(); public: void Reverse(); void Swap(List& s); void PrintSList(); //打印链表 void PushBack(const DataType& x); //在尾部插入一个节点 void Clear(); //链表置空 void PopBack(); void PushFront(DataType x); //头插 void PopFront(); //删除首节点 void Insert(LinkNode* pos, DataType x);//固定位置插入一个节点 void Erase(LinkNode* pos); //删除某一节点 LinkNode* Find(DataType x); //查找节点并返回这个节点的地址 int Amount(); //计算链表节点的数目 void Remove(DataType x); //查找某节点并删除 private: LinkNode* _head; //指向头结点 LinkNode* _tail; //指向尾节点 };
1 #include<iostream> 2 using namespace std; 3 #include<assert.h> 4 #include"List.h" 5 6 //节点类构造函数* 7 LinkNode::LinkNode(const DataType x) 8 :_data(x) 9 , _next(NULL) 10 , _prev(NULL) 11 {} 12 13 //链表类* 14 List::List() //构造函数 15 : _head(NULL) 16 , _tail(NULL) 17 {} 18 19 List::List(const List& s) //拷贝构造 20 : _head(NULL) 21 , _tail(NULL) 22 { 23 if (s._head == NULL) 24 { 25 return; 26 } 27 LinkNode* tmp = s._head; 28 while (tmp) 29 { 30 PushBack(tmp->_data); 31 tmp = tmp->_next; 32 } 33 34 } 35 36 //赋值运算符的重载(传统方法) 37 //SList & SList::operator=(const SList& s) 38 //{ 39 // if (this != &s) 40 // { 41 // _head = NULL; 42 // _tail = NULL; 43 // LinkNode* tmp = s._head; 44 // do{ 45 // PushBack(tmp->_data); 46 // tmp = tmp->_next; 47 // } while (tmp != s._head); 48 // } 49 // return *this; 50 //} 51 52 //赋值运算符的重载(高效写法)* 53 /*void SList::Swap(SList& s) 54 { 55 swap(_head, s._head); 56 swap(_tail, s._tail); 57 58 } 59 SList& SList::operator=(SList &s) 60 { 61 if (this != &s) 62 { 63 SList tmp(s); 64 Swap(tmp); 65 } 66 return *this; 67 }*/ 68 69 List& List::operator=(List &s) //赋值运算符的重载再优化(推荐写法) 70 { 71 if (this != &s) 72 { 73 swap(_head, s._head); 74 swap(_tail, s._tail); 75 } 76 return *this; 77 } 78 List::~List() //析构 79 { 80 Clear(); 81 } 82 83 void List::Reverse() //链表逆置(利用头插新节点的方法) 84 { 85 if (_head == NULL || _head== _tail) 86 { 87 return; 88 } 89 int ret = Amount(); 90 91 /* // 方法一(相当于用头插的方式重新建立链表) 92 _tail = new LinkNode(_head->_data); 93 LinkNode* begin = NULL; 94 LinkNode* tmp = _tail; 95 while (--ret) 96 { 97 LinkNode* del = _head; 98 _head = _head->_next; 99 delete del; 100 begin = new LinkNode(_head->_data); 101 begin->_next = tmp; 102 tmp->_prev = begin; 103 tmp = begin; 104 } 105 _head = begin;*/ 106 107 ////// 方法二(只是交换对称位置节点的数据)**(高效) 108 LinkNode* begin = _head; 109 LinkNode* end = _tail; 110 while (ret) 111 { 112 if (end->_next == begin) 113 break; 114 ret /= 2; 115 swap(begin->_data, end->_data); 116 begin = begin->_next; 117 end = end->_prev; 118 } 119 120 /*// 方法三 交换前驱和后继指针 121 swap(_head, _tail); 122 LinkNode* cur = _head; 123 while (cur) 124 { 125 swap(cur->_prev,cur->_next); 126 cur = cur->_next; 127 } 128 */ 129 130 } 131 132 //打印链表* 133 void List::PrintSList() 134 { 135 //头结点为空时,无需打印链表 136 if (_head == NULL) 137 { 138 cout << "This SList is Empty !" << endl; 139 return; 140 } 141 else 142 { 143 LinkNode* tmp = _head; 144 while (tmp) 145 { 146 cout << tmp->_data << "-->"; 147 tmp = tmp->_next; 148 } 149 cout <<"NULL"<< endl; 150 } 151 } 152 153 void List::PushBack(const DataType& x) //在尾部插入一个节点* 154 { 155 //如果链表为空,插入节点后只有一个节点,此时_head=_tail 156 if (_head == NULL) 157 { 158 _head = new LinkNode(x); 159 _tail = _head; 160 } 161 else 162 { 163 _tail->_next = new LinkNode(x); 164 _tail->_next->_prev=_tail; 165 _tail = _tail->_next; 166 } 167 } 168 169 void List::Clear() //链表置空* 170 { 171 LinkNode* begin = _head; 172 while (begin != _tail) 173 { 174 _head = _head->_next; 175 delete begin; 176 begin = _head; 177 } 178 _head = NULL; 179 _tail = NULL; 180 } 181 182 void List::PopBack() //尾删 183 { 184 if (_head == NULL) 185 { 186 cout << "This SList is empty !" << endl; 187 } 188 else if (_head == _tail) 189 { 190 delete _head; 191 _head = NULL; 192 _tail = NULL; 193 } 194 else 195 { 196 LinkNode* cur = _head; 197 while (cur->_next != _tail) 198 { 199 cur = cur->_next; 200 } 201 delete _tail; 202 _tail = cur; 203 _tail->_prev = cur->_prev; 204 _tail->_next = NULL; 205 } 206 } 207 208 void List::PushFront(DataType x) //头插* 209 { 210 if (_head == NULL) 211 { 212 PushBack(x); 213 } 214 else 215 { 216 LinkNode* tmp = _head; 217 _head = new LinkNode(x); 218 _head->_next = tmp; 219 tmp->_prev = _head; 220 } 221 } 222 223 void List::PopFront() //删除首节点 224 { 225 if (_head == NULL) 226 { 227 cout << "This SList is empty !" << endl; 228 return; 229 } 230 LinkNode* tmp = _head; 231 _head = _head->_next; 232 _head->_prev = NULL; 233 delete tmp; 234 } 235 236 //固定位置插入一个节点(这个函数需和Find函数搭配使用) 237 //先用Find函数找到新节点需要插入的位置 238 //(将Find函数的返回值传给Insert函数的参数pos),再在pos节点后面插入新节点x 239 void List::Insert(LinkNode* pos, DataType x) //* 240 { 241 assert(pos); 242 if (pos == _tail) 243 { 244 PushBack(x); 245 } 246 else 247 { 248 LinkNode* tmp = new LinkNode(x); 249 tmp->_next = pos->_next; 250 pos->_next = tmp; 251 tmp->_next->_prev = tmp; 252 tmp->_prev = pos; 253 } 254 } 255 256 //删除某一节点,同样,要先找到该节点并传参给Erase函数 257 void List::Erase(LinkNode* pos) 258 { 259 assert(pos); 260 if (pos == _tail) 261 { 262 PopBack(); 263 } 264 else if (pos == _head) 265 { 266 PopFront(); 267 } 268 else 269 { 270 pos->_prev->_next = pos->_next; 271 pos->_next->_prev = pos->_prev; 272 delete pos; 273 } 274 } 275 276 //查找节点并返回这个节点的地址 277 LinkNode* List::Find(DataType x) 278 { 279 if (_head == NULL) 280 { 281 cout << "This SList is empty !" << endl; 282 return NULL; 283 } 284 else 285 { 286 LinkNode* tmp = _head; 287 while (tmp != NULL) 288 { 289 if (tmp->_data == x) 290 { 291 return tmp; 292 } 293 tmp = tmp->_next; 294 } 295 return NULL; 296 } 297 } 298 299 int List::Amount() //计算链表节点的数目 300 { 301 if (_head == NULL) 302 { 303 return 0; 304 } 305 else 306 { 307 int count = 0; 308 LinkNode* cur = _head; 309 while (cur != _tail) 310 { 311 count++; 312 cur = cur->_next; 313 } 314 return ++count; 315 } 316 } 317 318 void List::Remove(DataType x) //查找某节点并删除 319 { 320 if (_head == NULL) 321 { 322 cout << "This SList is empty !" << endl; 323 } 324 else 325 { 326 LinkNode* tmp = Find(x); 327 if (tmp != NULL) 328 { 329 Erase(tmp); 330 } 331 } 332 }
1 #include"List.h" 2 #include<stdlib.h> 3 #include<iostream> 4 using namespace std; 5 6 void Test1() 7 { 8 List list1; 9 list1.PushBack(1); 10 list1.PushBack(2); 11 list1.PushBack(3); 12 list1.PushBack(4); 13 list1.PushBack(5); 14 list1.PushBack(6); 15 list1.PrintSList(); 16 17 /* List list2(list1); 18 list2.PrintSList();*/ 19 20 List list2=list1; 21 list2.PrintSList(); 22 //list2.PopBack(); 23 //list2.Clear(); 24 //list2.PushFront(0); 25 //list2.PopFront(); 26 27 //////检验Find函数 28 ////LinkNode* ret=list2.Find(4); 29 ////if (ret != NULL) 30 ////{ 31 //// cout << "ret:" << ret << " " << ret->_data << endl; 32 ////} 33 ////else 34 ////{ 35 //// cout << "Not exit !" << endl; 36 ////} 37 38 /* int ret=list2.Amount(); 39 cout << ret << endl;*/ 40 41 //list2.Erase(list2.Find(5)); 42 //list2.Insert(list2.Find(2), 0); 43 //list2.Remove(3); 44 list2.Reverse(); 45 list2.PrintSList(); 46 } 47 48 int main() 49 { 50 Test1(); 51 system("pause"); 52 }