- 线性表的基本概念介绍参阅:javascript:void(0)
- 前面的文章我们分别使用数组、vector的方式实现了线性表(javascript:void(0)、javascript:void(0)),本文我们可以使用单链表来实现线性表
-
本文代码下载链接:
- 方式1:公众号【多栖技术控小董】回复【3573】免费获取下载链接。
- 方式2:CSDN下载链接javascript:void(0)
- 方式3:Github下载链接https://github.com/dongyusheng/Interview-algorithm/tree/master/c%2B%2BAlgorithms(进入之后下载里面的chain.zip文件)
线性表类实现(class linearList、class chain)
template<typename T> class linearList { public: virtual ~linearList() {}; //当线性表为空时返回true virtual bool empty() const = 0; //返回线性表的元素个数 virtual int size() const = 0; //返回索引theIndex的元素 virtual T& get(int theIndex)const = 0; //返回元素theElement第一次出现时的索引 virtual int indexOf(const T& theElement) const = 0; //删除索引为theIndex的元素 virtual void earse(int theIndex) = 0; //把theElement插入线性表中索引为theIndex的位置上 virtual void insert(int theIndex, const T& theElement) = 0; //把线性表插入输出流out virtual void output(ostream& out)const = 0; };
template<typename T> class chain:public linearList<T> { public: chain(int initialCapacity = 10); chain(const chain<T>& other); ~chain(); bool empty() const; int size() const; T& get(int theIndex)const override; int indexOf(const T& theElement)const override; void earse(int theIndex)override; void insert(int theIndex, const T& theElement)override; void output(ostream& out)const override; private: void checkIndex(int theIndex)const; private: chainNode<T>* firstNode; int listSize; };
链表节点定义(struct chainNode)
template<typename T> struct chainNode { T element; chainNode<T> *next; chainNode() {} chainNode(const T& element) { this->element = element; } chainNode(const T& element,chainNode<T>* next) { this->element = element; this->next = next; } };
构造函数、拷贝构造、析构函数
- 复杂度:
- 构造函数:Θ(1)
- 拷贝构造:O(max{listSize,other.listSize})
- 析构函数:O(listSize)
template<typename T> chain<T>::chain(int initialCapacity = 10) { if (initialCapacity<=0) { ostringstream s; s << "Initial Capacity is " << initialCapacity << ",Must >=1"; throw illegalParamterValue(s.str().c_str()); } this->firstNode = nullptr; this->listSize = 0; } template<typename T> chain<T>::chain(const chain<T>& other) { this->listSize = other.listSize; if (this->listSize == 0) { this->firstNode = nullptr; this->listSize = 0; } chainNode<T>* otherNode = other.firstNode; this->firstNode = new chainNode<T>(otherNode->element); chainNode<T>* tempNode= this->firstNode; while (otherNode->next) { tempNode->next = new chainNode<T>(otherNode->next->element); tempNode = tempNode->next; otherNode = otherNode->next; } tempNode->next = nullptr; } template<typename T> chain<T>::~chain() { chainNode<T> *temp = firstNode; while (temp) { firstNode = firstNode->next; delete temp; temp = firstNode; } /*方式二 while (firstNode) { chainNode<T> *temp = firstNode->next; delete firstNode; firstNode = temp; } */ }
checkIndex、empty、size函数
template<typename T> void chain<T>::checkIndex(int theIndex)const { if((theIndex<0) || (theIndex>=listSize)){ ostringstream s; s << "List size is " << listSize << ",theIndex is " << theIndex; throw illegalParamterValue(s.str().c_str()); } }
template<typename T> bool chain<T>::empty() const { return (listSize == 0); }
template<typename T> int chain<T>::size() const { return listSize; }
get函数
- 必须通过指针遍历,所以时间复杂度:O(theIndex)
template<typename T> T& chain<T>::get(int theIndex)const { checkIndex(theIndex); int index = 0; chainNode<T> *tempNode = firstNode; while (index != theIndex) { tempNode = tempNode->next; index++; } return tempNode->element; }
indexOf函数
- 必须通过指针遍历,所以时间复杂度:O(theIndex)
template<typename T> int chain<T>::indexOf(const T& theElement) const { chainNode<T> *tempNode = firstNode; for (int i = 0; i < listSize; ++i) { if (tempNode->element == theElement) { return i; } tempNode = tempNode->next; } return -1; /*方式二 chainNode<T> *tempNode = firstNode; int index = 0; while ((tempNode != nullptr) &&(tempNode->element!= theElement)) { tempNode = tempNode->next; ++index; } if (tempNode == nullptr) { return -1; } return index; */ }
earse函数
- 复杂度:O(theIndex)
template<typename T> void chain<T>::earse(int theIndex) { checkIndex(theIndex); chainNode<T> *deleteNode; //如果是头结点 if (theIndex == 0) { deleteNode = firstNode; firstNode = firstNode->next; } else { int index = 0; chainNode<T> *tempNode = firstNode; while (index<theIndex - 1) { tempNode = tempNode->next; } deleteNode = tempNode->next; tempNode->next= tempNode->next->next; } delete deleteNode; deleteNode = nullptr; listSize--; }
insert函数
- 复杂度:O(theIndex)
template<typename T> void chain<T>::insert(int theIndex, const T& theElement) { if ((theIndex<0) || (theIndex>listSize)) { ostringstream s; s << "List size is " << listSize << ",theIndex is " << theIndex; throw illegalParamterValue(s.str().c_str()); } //如果是插入头结点 if (theIndex == 0) { firstNode = new chainNode<T>(theElement,firstNode); } else { int index = 0; chainNode<T> *temptNode = firstNode; while (index < theIndex-1) { temptNode = temptNode->next; index++; } temptNode->next = new chainNode<T>(theElement, temptNode->next); } listSize++; }
output函数、<<重载函数
- 复杂度都是:O(listSize)
- <<重载函数是全局函数
template<typename T> void chain<T>::output(ostream& out)const { for (chainNode<T>* tempNode = firstNode; tempNode != nullptr; tempNode = tempNode->next) { out << tempNode->element << " "; } }
template<typename T> ostream& operator<<(ostream& out,const chain<T>& x) { x.output(out); return out; }
三、迭代器设计演示案例
int main() { chain<int> *myChain = new chain<int>(); cout << "Current size is" << myChain->size() << endl; cout << "All number is "; myChain->output(cout); cout << endl << endl; cout << "Insert 1,2,3"<< endl; myChain->insert(0,1); myChain->insert(1, 2); myChain->insert(2, 3); cout << "Current size is" << myChain->size() << endl; cout << "All number is "; myChain->output(cout); cout << endl; cout << "Index 0 value is "<< myChain->get(0)<< endl; cout << "Index 1 value is " << myChain->get(1) << endl; cout << "Index 2 value is " << myChain->get(2) << endl; cout << "The index if value 1 is " << myChain->indexOf(1) << endl; cout << "The index if value 2 is " << myChain->indexOf(2) << endl; cout << "The index if value 3 is " << myChain->indexOf(3) << endl; cout << endl << endl; myChain->earse(1); cout << "earse 2"<< endl; cout << "Current size is" << myChain->size() << endl; cout << "All number is "; myChain->output(cout); cout << endl; cout << "Index 0 value is " << myChain->get(0) << endl; cout << "Index 1 value is " << myChain->get(1) << endl; cout << "The index if value 1 is " << myChain->indexOf(1) << endl; cout << "The index if value 3 is " << myChain->indexOf(3) << endl; cout << endl << endl; myChain->insert(1,2); cout << "Insert 2" << endl; cout << "Current size is" << myChain->size() << endl; cout << "All number is "; myChain->output(cout); cout << endl; cout << "Index 0 value is " << myChain->get(0) << endl; cout << "Index 1 value is " << myChain->get(1) << endl; cout << "Index 2 value is " << myChain->get(2) << endl; cout << "The index if value 1 is " << myChain->indexOf(1) << endl; cout << "The index if value 2 is " << myChain->indexOf(2) << endl; cout << "The index if value 3 is " << myChain->indexOf(3) << endl; return 0; }
- 在单链表中,使用指针next,我们只能从一个节点找到它的后继,但是不能访问其前驱节点。多以,下面的迭代器只重载了++运算符
template<typename T> class chain:public linearList<T> { /***/ public: class iterator { public: iterator(chainNode<T>* other=nullptr) { node = other; } /*iterator& operator=(const iterator<T>& other) { node = other.node; return *this; }*/ T& operator*()const { return node->element; } T* operator->()const { return &node->element; } iterator& operator++() { node = node->next; return *this; } iterator operator++(int) { iterator old = *this; node = node->next; return old; } bool operator==(const iterator other)const { return (node == other.node); } bool operator!=(const iterator other)const { return node != other.node; } protected: chainNode<T> *node; }; iterator begin() { return iterator(firstNode); } iterator end() { return iterator(nullptr); } /***/ };
演示效果
int main() { chain<int> *myChain = new chain<int>(); cout << "Current size is" << myChain->size() << endl; cout << "All number is "; myChain->output(cout); cout << endl << endl; cout << "Insert 1,2,3"<< endl; myChain->insert(0,1); myChain->insert(1, 2); myChain->insert(2, 3); chain<int>::iterator iter = myChain->begin(); for (; iter != myChain->end(); iter++) { cout << *iter<<" "; } cout << endl; return 0; }