第二十二课 单链表的具体实现
Posted wanmeishenghuo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第二十二课 单链表的具体实现相关的知识,希望对你有一定的参考价值。
本节目标:
添加LinkList.h文件:
1 #ifndef LINKLIST_H 2 #define LINKLIST_H 3 4 #include "List.h" 5 #include "Exception.h" 6 7 namespace DTLib 8 { 9 10 template < typename T > 11 class LinkList : public List<T> 12 { 13 protected: 14 struct Node : public Object 15 { 16 T value; 17 Node* next; 18 }; 19 20 mutable Node m_header; 21 int m_length; 22 public: 23 LinkList() 24 { 25 m_header.next = NULL; 26 m_length = 0; 27 } 28 29 bool insert(const T& e) 30 { 31 return insert(m_length, e); 32 } 33 34 bool insert(int i, const T& e) 35 { 36 bool ret = ((0 <= i) && (i <= m_length)); 37 38 if( ret ) 39 { 40 Node* node = new Node(); 41 42 if( node != NULL ) 43 { 44 Node* current = &m_header; 45 46 for(int p=0; p<i; p++) 47 { 48 current = current->next; 49 } 50 51 node->value = e; 52 node->next = current->next; 53 current->next = node; 54 55 m_length++; 56 } 57 else 58 { 59 THROW_EXCEPTION(NoEnoughMemoryException, "No memery to insert new element..."); 60 } 61 } 62 63 return ret; 64 } 65 66 bool remove(int i) 67 { 68 bool ret = ((0 <= i) && (i < m_length)); 69 70 if( ret ) 71 { 72 Node* current = &m_header; 73 74 for(int p=0; p<i; p++) 75 { 76 current = current->next; 77 } 78 79 Node* toDel = current->next; 80 81 current->next = toDel->next; 82 83 delete toDel; 84 85 m_length--; 86 } 87 88 return ret; 89 } 90 91 bool set(int i, const T& e) 92 { 93 bool ret = ((0 <= i) && (i < m_length)); 94 95 if( ret ) 96 { 97 Node* current = &m_header; 98 99 for(int p=0; p<i; p++) 100 { 101 current = current->next; 102 } 103 104 current->next->value = e; 105 } 106 107 return ret; 108 } 109 110 bool get(int i, T& e) const 111 { 112 bool ret = ((0 <= i) && (i < m_length)); 113 114 if( ret ) 115 { 116 Node* current = &m_header; 117 118 for(int p=0; p<i; p++) 119 { 120 current = current->next; 121 } 122 123 e = current->next->value; 124 } 125 126 return ret; 127 } 128 129 int length() const 130 { 131 return m_length; 132 } 133 134 void clear() 135 { 136 while( m_header.next ) 137 { 138 Node* toDel = m_header.next; 139 140 m_header.next = toDel->next; 141 142 delete toDel; 143 } 144 145 m_length = 0; 146 } 147 148 ~LinkList() 149 { 150 clear(); 151 } 152 }; 153 154 } 155 156 #endif // LINKLIST_H
第110行的get是const函数,116行我们取m_header的指针,这时编译器会认为我们要改变m_header,编译会报错,因此,我们在第20行给m_header这个变量加上mutable属性。
测试程序如下:
1 #include <iostream> 2 #include "LinkList.h" 3 4 5 using namespace std; 6 using namespace DTLib; 7 8 9 int main() 10 { 11 12 LinkList<int> list; 13 14 for(int i = 0; i<5; i++) 15 { 16 list.insert(i); 17 } 18 19 for(int i = 0; i < list.length(); i++) 20 { 21 int v = 0; 22 23 list.get(i, v); 24 25 cout << v << endl; 26 } 27 return 0; 28 }
运行结果如下:
get函数的使用不是很方便,我们添加一个重载函数:
1 #ifndef LINKLIST_H 2 #define LINKLIST_H 3 4 #include "List.h" 5 #include "Exception.h" 6 7 namespace DTLib 8 { 9 10 template < typename T > 11 class LinkList : public List<T> 12 { 13 protected: 14 struct Node : public Object 15 { 16 T value; 17 Node* next; 18 }; 19 20 mutable Node m_header; 21 int m_length; 22 public: 23 LinkList() 24 { 25 m_header.next = NULL; 26 m_length = 0; 27 } 28 29 bool insert(const T& e) 30 { 31 return insert(m_length, e); 32 } 33 34 bool insert(int i, const T& e) 35 { 36 bool ret = ((0 <= i) && (i <= m_length)); 37 38 if( ret ) 39 { 40 Node* node = new Node(); 41 42 if( node != NULL ) 43 { 44 Node* current = &m_header; 45 46 for(int p=0; p<i; p++) 47 { 48 current = current->next; 49 } 50 51 node->value = e; 52 node->next = current->next; 53 current->next = node; 54 55 m_length++; 56 } 57 else 58 { 59 THROW_EXCEPTION(NoEnoughMemoryException, "No memery to insert new element..."); 60 } 61 } 62 63 return ret; 64 } 65 66 bool remove(int i) 67 { 68 bool ret = ((0 <= i) && (i < m_length)); 69 70 if( ret ) 71 { 72 Node* current = &m_header; 73 74 for(int p=0; p<i; p++) 75 { 76 current = current->next; 77 } 78 79 Node* toDel = current->next; 80 81 current->next = toDel->next; 82 83 delete toDel; 84 85 m_length--; 86 } 87 88 return ret; 89 } 90 91 bool set(int i, const T& e) 92 { 93 bool ret = ((0 <= i) && (i < m_length)); 94 95 if( ret ) 96 { 97 Node* current = &m_header; 98 99 for(int p=0; p<i; p++) 100 { 101 current = current->next; 102 } 103 104 current->next->value = e; 105 } 106 107 return ret; 108 } 109 110 T get(int i) const 111 { 112 T ret; 113 114 if( get(i, ret) ) 115 { 116 return ret; 117 } 118 else 119 { 120 THROW_EXCEPTION(IndexOutOfBoundsException, "Invalid parameter i to get element ..."); 121 } 122 123 return ret; 124 } 125 126 bool get(int i, T& e) const 127 { 128 bool ret = ((0 <= i) && (i < m_length)); 129 130 if( ret ) 131 { 132 Node* current = &m_header; 133 134 for(int p=0; p<i; p++) 135 { 136 current = current->next; 137 } 138 139 e = current->next->value; 140 } 141 142 return ret; 143 } 144 145 int length() const 146 { 147 return m_length; 148 } 149 150 void clear() 151 { 152 while( m_header.next ) 153 { 154 Node* toDel = m_header.next; 155 156 m_header.next = toDel->next; 157 158 delete toDel; 159 } 160 161 m_length = 0; 162 } 163 164 ~LinkList() 165 { 166 clear(); 167 } 168 }; 169 170 } 171 172 #endif // LINKLIST_H
第110行为添加的重载的get函数,这个函数直接返回需要的值。
测试程序如下:
1 #include <iostream> 2 #include "LinkList.h" 3 4 5 using namespace std; 6 using namespace DTLib; 7 8 9 int main() 10 { 11 12 LinkList<int> list; 13 14 for(int i = 0; i<5; i++) 15 { 16 list.insert(i); 17 } 18 19 for(int i = 0; i < list.length(); i++) 20 { 21 cout << list.get(i) << endl; 22 } 23 24 list.remove(2); 25 26 for(int i = 0; i < list.length(); i++) 27 { 28 cout << list.get(i) << endl; 29 } 30 31 return 0; 32 }
结果如下:
问题:
头结点是否存在隐患?实现代码是否需要优化?
我们定义的Node结构里面,只用到了next成员,而value成员是由用户指定的,如果用户自己定义了一个类型Test,在这个类型的构造函数中抛出异常。 如果用户使用这个Test类型来定义list的话,就会出现问题。
测试程序:
结果如下:
我们根本没有创建有问题的类Test的对象,只是创建了一个单链表LinkList的对象,而这确报错了。
没有创建Test类对象,就报错了,这时库的创建者是要负责的,而不是用户来负责。
以上是关于第二十二课 单链表的具体实现的主要内容,如果未能解决你的问题,请参考以下文章
Golang✔️走进 Go 语言✔️ 第二十二课 json & 文件读写