C++实现单链表和子类栈(Stack)及单向队列(Queue)
刚刚开始学习c++。之前c的内容掌握的也不多,基本只是一本概论课的程度,以前使用c的struct写过的链表、用python写过简单的数据结构,就试着把两者用c++写出来,也是对c++的class,以及继承中的public/protected/private的性质进行初步了解。第一次写头文件.h和源文件.cpp分开的c++代码。过程中参考了prolyn和kgvito的代码,基本就是百度“单链表 c++”的前几个搜索结果。
节点listnode还是用struct来写了,因为我想节点除了构造没有什么方法需要实现,变量和构造也总是需要处于public的状态方便其他类函数调用。
栈是保持先进后出(first in last out, 或者filo)的数据结构,在这里只是定义了最基本的五种方法,实现从尾部添加、从尾部弹出;队列是保持先进先出(first in first out, fifo)的数据结构,同样定义了最基本的方法实现从尾部添加从头部弹出。二者我都使用了private继承,因为除了重新封装list的几种方法外,多数list的方法都不需要出现在这两种数据结构中,我认为禁止public访问这些方法比较好。
1 // linked_list.h 2 // base class linked list "linklist", derived "linkstack" & "linkqueue" 3 typedef int datatype; 4 5 // constructing struct "listnode" 6 struct listnode 7 { 8 datatype nodeval; 9 listnode* nextnode; 10 listnode(const datatype x); // listnode construct func 11 }; 12 13 // constructing base class "linklist" 14 class linklist 15 { 16 private: // private variables headnode & tailnode 17 listnode* headnode; 18 listnode* tailnode; 19 // construction functions, and operator overload 20 public: 21 linklist(); 22 linklist(const linklist& lista); 23 linklist& operator=(linklist& lista); 24 datatype operator[](int index); 25 // other functions, public 26 public: 27 bool isempty(); 28 void printlist(); 29 void pushback(const datatype& x); 30 void pushfront(const datatype& x); 31 void popback(); 32 void popfront(); 33 datatype peekback(); 34 datatype peekfront(); 35 void insertnext(listnode* pos, datatype x); 36 void deletenext(listnode* pos); 37 void delete(listnode* pos); 38 void clear(); 39 void remove(datatype x); 40 void removeall(datatype x); 41 void sort(); 42 int getlength(); 43 listnode* find(datatype x); 44 }; 45 46 // derived class linkstack 47 class linkstack : private linklist 48 { 49 public: 50 linkstack(); 51 linkstack(const linkstack& stack1); 52 linkstack& operator=(linkstack& stack1); 53 // the least functions needed 54 public: 55 bool isempty(); 56 int getsize(); 57 void pushback(const datatype& x); 58 void popback(); 59 datatype peekback(); 60 }; 61 62 // derived class linkqueue 63 class linkqueue : private linklist 64 { 65 public: 66 linkqueue(); 67 linkqueue(const linkqueue& queue1); 68 linkqueue& operator=(linkqueue& queue1); 69 70 public: 71 bool isempty(); 72 int getsize(); 73 void pushback(const datatype& x); 74 void popfront(); 75 datatype peekfront(); 76 }
对struct listnode,class linklist, linkstack, linkqueue的方法的具体实现,后两者基本只是对于linklist的重新封装,为了能在private继承的子类中实现,也不得不在linklist中添加了一些没什么用处的函数。其中构造函数和赋值下标运算重载的写法都是现学的…如果现学的不到位请不吝赐教!
1 #include <iostream> 2 #include "linked_list.h" 3 using namespace std; 4 // construction func for listnode 5 listnode::listnode(const datatype x) 6 :nodeval(x), nextnode(nullptr) 7 {} 8 // construction funcs for linklist 9 linklist::linklist() // without argument 10 : headnode(nullptr), tailnode(nullptr) 11 {} 12 13 linklist::linklist(const linklist& lista) // with argument 14 : headnode(nullptr), tailnode(nullptr) 15 { 16 if (lista.headnode) { 17 listnode* tmp = lista.headnode; 18 while (tmp->nextnode) { 19 pushback(tmp->nodeval); 20 tmp = tmp->nextnode; 21 } 22 pushback(tmp->nodeval); 23 } 24 } 25 // operator reload = 26 linklist& linklist::operator=(linklist &lista) { 27 if (this != &lista) { 28 swap(headnode, lista.headnode); 29 swap(tailnode, lista.tailnode); 30 } 31 return *this; 32 } 33 // operator reload [](index) 34 datatype linklist::operator[](int index) { 35 if (index < 0 || headnode == nullptr) { 36 cout << "invalid index!" << endl; 37 return -1; 38 } 39 else { 40 listnode* tmp = headnode; 41 int i; 42 while (tmp != nullptr && i < index) { 43 tmp = tmp->nextnode; 44 i++; 45 } 46 if (tmp == nullptr) { 47 cout << "invalid index!" << endl; 48 return -1; 49 } 50 else { 51 return tmp->nodeval; 52 } 53 } 54 } 55 56 bool linklist::isempty() { 57 if (headnode) { 58 return true; 59 } 60 else { 61 return false; 62 } 63 } 64 65 int linklist::getlength() { 66 int count = 0; 67 listnode* tmp = headnode; 68 while (tmp) { 69 count++; 70 tmp = tmp->nextnode; 71 } 72 return count; 73 } 74 75 void linklist::printlist() { 76 listnode* tmp = headnode; 77 if (tmp) { 78 cout << tmp->nodeval; 79 tmp = tmp->nextnode; 80 while (tmp) { 81 cout << "->" << tmp->nodeval; 82 tmp = tmp->nextnode; 83 } 84 cout << endl; 85 } 86 else { 87 cout << "empty linked list!" << endl; 88 } 89 } 90 91 void linklist::pushback(const datatype& x) { 92 if (headnode) { 93 tailnode->nextnode = new listnode(x); 94 tailnode = tailnode->nextnode; 95 } 96 else { 97 headnode = new listnode(x); 98 tailnode = headnode; 99 } 100 } 101 102 void linklist::pushfront(const datatype& x) { 103 if (headnode) { 104 listnode* tmp = new listnode(x); 105 tmp->nextnode = headnode; 106 headnode = tmp; 107 } 108 else { 109 headnode = new listnode(x); 110 tailnode = headnode; 111 } 112 } 113 114 void linklist::popback() { 115 if (headnode) { 116 if (headnode->nextnode) { 117 listnode* tmp = headnode; 118 while (tmp->nextnode != tailnode) { 119 tmp = tmp->nextnode; 120 } 121 delete tailnode; 122 tmp->nextnode = nullptr; 123 tailnode = tmp; 124 } 125 else { 126 delete headnode; 127 headnode = nullptr; 128 tailnode = nullptr; 129 } 130 } 131 else { 132 cout << "empty linked list!" << endl; 133 } 134 } 135 136 void linklist::popfront() { 137 if (headnode) { 138 if (headnode->nextnode) { 139 listnode* tmp = headnode->nextnode; 140 delete headnode; 141 headnode = tmp; 142 } 143 else { 144 delete headnode; 145 headnode = nullptr; 146 tailnode = nullptr; 147 } 148 } 149 else { 150 cout << "empty linked list!" << endl; 151 } 152 } 153 154 datatype linklist::peekback() { 155 if (tailnode) { 156 return tailnode->nodeval; 157 } 158 else { 159 cout << "empty linked list!" << endl; 160 return -1; 161 } 162 } 163 164 datatype linklist::peekfront() { 165 if (headnode) { 166 return headnode->nodeval; 167 } 168 else { 169 cout << "empty linked list!" << endl; 170 return -1; 171 } 172 } 173 174 listnode* linklist::find(datatype x) { 175 listnode* targetnode = headnode; 176 while (targetnode) { 177 if (targetnode->nodeval == x) {break;} 178 } 179 return targetnode; 180 } 181 182 void linklist::insertnext(listnode* pos, datatype x) { 183 if (pos) { 184 if (pos == tailnode) { 185 listnode* tmp = new listnode(x); 186 pos->nextnode = tmp; 187 tailnode = tmp; 188 } 189 else { 190 listnode* tmp = new listnode(x); 191 tmp->nextnode = pos->nextnode; 192 pos->nextnode = tmp; 193 } 194 } 195 else { 196 cout << "invalid position!" << endl; 197 } 198 } 199 200 void linklist::deletenext(listnode* pos) { 201 if (pos) { 202 if (pos == tailnode) { 203 cout << "invalid node!" << endl; 204 } 205 else { 206 listnode* tmp = (pos->nextnode)->nextnode; 207 delete pos->nextnode; 208 pos->nextnode = tmp; 209 } 210 } 211 else { 212 cout << "invalid node!" << endl; 213 } 214 } 215 216 void linklist::remove(datatype x) { 217 if (headnode) { 218 if (headnode->nextnode) { 219 listnode* tmp = headnode; 220 while (tmp->nextnode) { 221 if ((tmp->nextnode)->nodeval == x) { 222 deletenext(tmp); 223 break; 224 } 225 tmp = tmp->nextnode; 226 } 227 } 228 else { 229 if (headnode->nodeval == x) {popfront();} 230 } 231 } 232 } 233 234 void linklist::removeall(datatype x) { 235 if (headnode) { 236 listnode* tmp = headnode; 237 while (tmp->nextnode) { 238 if ((tmp->nextnode)->nodeval == x) { 239 if (tmp->nextnode == tailnode){ 240 popback(); 241 break; 242 } 243 else {deletenext(tmp);} 244 } 245 tmp = tmp->nextnode; 246 } 247 if (tmp->nodeval == x) { 248 popback(); 249 } 250 } 251 } 252 253 void linklist::clear() { 254 if (headnode) { 255 listnode* prev = headnode; 256 listnode* tmp; 257 while (prev->nextnode) { 258 tmp = prev->nextnode; 259 delete prev; 260 prev = tmp; 261 } 262 headnode = nullptr; 263 tailnode = nullptr; 264 } 265 } 266 // construction funcs for linkstack 267 linkstack::linkstack() // without arguments 268 :linklist() 269 {} 270 271 linkstack::linkstack(const linkstack& stack1) // with an argument 272 :linklist(stack1) 273 {} 274 // other public funcs for linkstack 275 bool linkstack::isempty() { 276 return linklist::isempty(); 277 } 278 279 int linkstack::getsize() { 280 return linklist::getlength(); 281 } 282 283 void linkstack::pushback(const datatype& x) { 284 linklist::pushback(x); 285 } 286 287 void linkstack::popback() { 288 linklist::popback(); 289 } 290 291 datatype linkstack::peekback() { 292 return linklist::peekback(); 293 } 294 // construction funcs for linkqueue 295 linkqueue::linkqueue() 296 :linklist() 297 {} 298 299 linkqueue::linkqueue(const linkqueue& queue1) 300 :linklist(queue1) 301 {} 302 // other public funcs for linkqueue 303 bool linkqueue::isempty() { 304 return linklist::isempty(); 305 } 306 307 int linkqueue::getsize() { 308 return linklist::getlength(); 309 } 310 311 void linkqueue::pushback(const datatype& x) { 312 linklist::pushback(x); 313 } 314 315 void linkqueue::popfront() { 316 linklist::popfront(); 317 } 318 319 datatype linkqueue::peekfront() { 320 return linklist::peekfront(); 321 }
最后还有测试代码,和主题没什么关系,但是从以前用python学习数据结构开始我就喜好把测试代码写成假交互式,所以索性贴在这里方便取用。
1 #include <iostream> 2 #include "linked_list.h" 3 #include <stdlib.h> 4 #include <map> 5 6 using namespace std; 7 8 static map<string, int>stringval { 9 {"exit", 0}, 10 {"printlist", 1}, 11 {"pushback", 2}, 12 {"pushfront", 3}, 13 {"popback", 4}, 14 {"popfront", 5}, 15 {"clear", 6}, 16 {"remove", 7}, 17 {"removeall", 8}, 18 {"sort", 9}, 19 {"getlength", 10}, 20 {"index", 11}, 21 {"peekback", 12}, 22 {"peekfront", 13} 23 }; 24 25 int test_list() { 26 linklist list1; 27 cout << ">> linked list tesing.\n" 28 ">> enter a direction, namely printlist, pushback, pushfront, popback, peekback, " 29 "popfront, peekfront, clear, remove, removeall, sort, getlength or index," 30 "enter exit to exit." << endl; 31 string direction; 32 datatype parameter; 33 int param; 34 while (1) { 35 cout << ">> "; 36 cout.flush(); 37 cin >> direction; 38 switch(stringval[direction]) 39 { 40 case 0: 41 return 0; 42 case 1: 43 list1.printlist(); 44 break; 45 case 2: 46 cin >> parameter; 47 list1.pushback(parameter); 48 break; 49 case 3: 50 cin >> parameter; 51 list1.pushfront(parameter); 52 break; 53 case 4: 54 list1.popback(); 55 break; 56 case 5: 57 list1.popfront(); 58 break; 59 case 6: 60 list1.clear(); 61 break; 62 case 7: 63 cin >> parameter; 64 list1.remove(parameter); 65 break; 66 case 8: 67 cin >> parameter; 68 list1.removeall(parameter); 69 break; 70 /* case 9: 71 list1.sort(); 72 break;*/ 73 case 10: 74 param = list1.getlength(); 75 cout << ">> " << param << endl; 76 break; 77 case 11: 78 cin >> param; 79 parameter = list1[param]; 80 cout << ">> " << parameter << endl; 81 break; 82 case 12: 83 parameter = list1.peekback(); 84 cout << ">> " << parameter << endl; 85 break; 86 case 13: 87 parameter = list1.peekfront(); 88 cout << ">> " << parameter << endl; 89 } 90 } 91 return 0; 92 } 93 94 int test_stack() { 95 linkstack stack1; 96 cout << ">> linked list stack tesing.\n" 97 ">> enter a direction, namely pushback, popback or peekback, " 98 "enter exit to exit." << endl; 99 string direction; 100 datatype parameter; 101 int param; 102 while (1) { 103 cout << ">> "; 104 cout.flush(); 105 cin >> direction; 106 switch(stringval[direction]) 107 { 108 case 0: 109 return 0; 110 case 2: 111 cin >> parameter; 112 stack1.pushback(parameter); 113 break; 114 case 4: 115 stack1.popback(); 116 break; 117 case 12: 118 parameter = stack1.peekback(); 119 cout << ">> " << parameter << endl; 120 break; 121 } 122 } 123 return 0; 124 } 125 126 int main() { 127 test_stack(); 128 return 0; 129 }
下一篇: 自媒体如何打造抖音ip达人,爆粉玩法分享