当前位置: 首页 > news >正文

线性表—链式描述

一、单向链表代码

chainNode.h(链表节点的结构定义)

// chain node#ifndef chainNode_
#define chainNode_template <class T>
struct chainNode 
{// data membersT element;chainNode<T> *next;// methodschainNode() {}chainNode(const T& element){this->element = element;}chainNode(const T& element, chainNode<T>* next){this->element = element;this->next = next;}
};#endif

节点chainNode数据成员:element为元素

                  *next指向下一节点的指针

chain.h

// linked implementation of a linear list
// derives from abstract class linearList just to make sure
// all methods of the ADT are implemented#ifndef chain_
#define chain_#include<iostream>
#include<sstream>
#include<string>
#include "linearList.h"
#include "chainNode.h"
#include "myExceptions.h"using namespace std;class linkedDigraph;
template <class T> class linkedWDigraph;template<class T>
class chain : public linearList<T> 
{friend linkedDigraph;friend linkedWDigraph<int>;friend linkedWDigraph<float>;friend linkedWDigraph<double>;public:// constructor, copy constructor and destructorchain(int initialCapacity = 10);chain(const chain<T>&);~chain();// ADT methodsbool empty() const {return listSize == 0;}int size() const {return listSize;}T& get(int theIndex) const;int indexOf(const T& theElement) const;void erase(int theIndex);void insert(int theIndex, const T& theElement);void output(ostream& out) const;protected:void checkIndex(int theIndex) const;// throw illegalIndex if theIndex invalidchainNode<T>* firstNode;  // pointer to first node in chainint listSize;             // number of elements in list
};template<class T>
chain<T>::chain(int initialCapacity)
{// Constructor.if (initialCapacity < 1){ostringstream s;s << "Initial capacity = " << initialCapacity << " Must be > 0";throw illegalParameterValue(s.str());}firstNode = NULL;listSize = 0;
}template<class T>
chain<T>::chain(const chain<T>& theList)
{// Copy constructor.listSize = theList.listSize;if (listSize == 0){// theList is emptyfirstNode = NULL;return;}// non-empty listchainNode<T>* sourceNode = theList.firstNode;// node in theList to copy fromfirstNode = new chainNode<T>(sourceNode->element);// copy first element of theListsourceNode = sourceNode->next;chainNode<T>* targetNode = firstNode;// current last node in *thiswhile (sourceNode != NULL){// copy remaining elementstargetNode->next = new chainNode<T>(sourceNode->element);targetNode = targetNode->next;sourceNode = sourceNode->next;}targetNode->next = NULL; // end the chain
}template<class T>
chain<T>::~chain()
{// Chain destructor. Delete all nodes in chain.while (firstNode != NULL){// delete firstNodechainNode<T>* nextNode = firstNode->next;delete firstNode;firstNode = nextNode;}
}template<class T>
void chain<T>::checkIndex(int theIndex) const
{// Verify that theIndex is between 0 and listSize - 1.if (theIndex < 0 || theIndex >= listSize){ostringstream s;s << "index = " << theIndex << " size = " << listSize;throw illegalIndex(s.str());}}template<class T>
T& chain<T>::get(int theIndex) const
{// Return element whose index is theIndex.// Throw illegalIndex exception if no such element.checkIndex(theIndex);// move to desired nodechainNode<T>* currentNode = firstNode;for (int i = 0; i < theIndex; i++)currentNode = currentNode->next;return currentNode->element;
}template<class T>
int chain<T>::indexOf(const T& theElement) const
{// Return index of first occurrence of theElement.// Return -1 if theElement not in list.// search the chain for theElementchainNode<T>* currentNode = firstNode;int index = 0;  // index of currentNodewhile (currentNode != NULL && currentNode->element != theElement){// move to next nodecurrentNode = currentNode->next;index++;}// make sure we found matching elementif (currentNode == NULL)return -1;elsereturn index;
}template<class T>
void chain<T>::erase(int theIndex)
{// Delete the element whose index is theIndex.// Throw illegalIndex exception if no such element.checkIndex(theIndex);// valid index, locate node with element to deletechainNode<T>* deleteNode;if (theIndex == 0){// remove first node from chaindeleteNode = firstNode;firstNode = firstNode->next;}else {  // use p to get to predecessor of desired nodechainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;deleteNode = p->next;p->next = p->next->next; // remove deleteNode from chain}listSize--;delete deleteNode;
}template<class T>
void chain<T>::insert(int theIndex, const T& theElement)
{// Insert theElement so that its index is theIndex.if (theIndex < 0 || theIndex > listSize){// invalid indexostringstream s;s << "index = " << theIndex << " size = " << listSize;throw illegalIndex(s.str());}if (theIndex == 0)// insert at frontfirstNode = new chainNode<T>(theElement, firstNode);else{  // find predecessor of new elementchainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;// insert after pp->next = new chainNode<T>(theElement, p->next);}listSize++;
}template<class T>
void chain<T>::output(ostream& out) const
{// Put the list into the stream out.for (chainNode<T>* currentNode = firstNode;currentNode != NULL;currentNode = currentNode->next)out << currentNode->element << "  ";
}// overload <<
template <class T>
ostream& operator<<(ostream& out, const chain<T>& x){x.output(out); return out;}#endif

类chain数据成员:firstNode首节点

                               listSize元素个数

构造函数:

初始化头指针指向空,个数为0。

template<class T>
chain<T>::chain(int initialCapacity)
{// Constructor.if (initialCapacity < 1){ostringstream s;s << "Initial capacity = " << initialCapacity << " Must be > 0";throw illegalParameterValue(s.str());}firstNode = NULL;listSize = 0;
}

复制构造函数:

先将listSize复制,判断若为0则头指针指向空返回。

不为空:

sourceNode:遍历原链表(theList)的指针,从第一个数据节点开始,依次指向待拷贝的节点;

targetNode:构建新链表的指针,从新链表的第一个节点开始,依次指向新创建的节点(用于链接后续节点)

(1)拷贝原链表的 “第一个数据节点”

       1.让sourceNode指向原链表的第一个数据节点

       2. 为新链表创建第一个数据节点(用原链表第一个节点的元素初始化)

       3. sourceNode后移,指向原链表的下一个节点(准备拷贝下一个元素)
4. targetNode指向新链表的第一个节点(后续用来链接新节点)

(2)循环拷贝原链表的 “剩余节点”

    1. 在targetNode后面创建新节点(用当前sourceNode的元素初始化)
2. targetNode后移,指向刚创建的新节点(准备下一次链接)
3. sourceNode后移,指向原链表的下一个待拷贝节点

template<class T>
chain<T>::chain(const chain<T>& theList)
{// Copy constructor.listSize = theList.listSize;if (listSize == 0){// theList is emptyfirstNode = NULL;return;}// non-empty listchainNode<T>* sourceNode = theList.firstNode;// node in theList to copy fromfirstNode = new chainNode<T>(sourceNode->element);// copy first element of theListsourceNode = sourceNode->next;chainNode<T>* targetNode = firstNode;// current last node in *thiswhile (sourceNode != NULL){// copy remaining elementstargetNode->next = new chainNode<T>(sourceNode->element);targetNode = targetNode->next;sourceNode = sourceNode->next;}targetNode->next = NULL; // end the chain
}

析构函数:

while循环,辅助指针nextNode,不断清除firstNode的内存。并将firstNode指向nextNode。

template<class T>
chain<T>::~chain()
{// Chain destructor. Delete all nodes in chain.while (firstNode != NULL){// delete firstNodechainNode<T>* nextNode = firstNode->next;delete firstNode;firstNode = nextNode;}
}

方法checkIndex:

template<class T>
void chain<T>::checkIndex(int theIndex) const
{// Verify that theIndex is between 0 and listSize - 1.if (theIndex < 0 || theIndex >= listSize){ostringstream s;s << "index = " << theIndex << " size = " << listSize;throw illegalIndex(s.str());}}

方法get(根据索引返回元素):

for循环,循环theIndex次,用辅助指针遍历。

template<class T>
T& chain<T>::get(int theIndex) const
{// Return element whose index is theIndex.// Throw illegalIndex exception if no such element.checkIndex(theIndex);// move to desired nodechainNode<T>* currentNode = firstNode;for (int i = 0; i < theIndex; i++)currentNode = currentNode->next;return currentNode->element;
}

方法indexOf(返回元素所在索引):

循环终止条件:找到或遍历完

template<class T>
int chain<T>::indexOf(const T& theElement) const
{// Return index of first occurrence of theElement.// Return -1 if theElement not in list.// search the chain for theElementchainNode<T>* currentNode = firstNode;int index = 0;  // index of currentNodewhile (currentNode != NULL && currentNode->element != theElement){// move to next nodecurrentNode = currentNode->next;index++;}// make sure we found matching elementif (currentNode == NULL)return -1;elsereturn index;
}

方法erase(按索引清除节点):

若为第一个节点:辅助指针指向首节点,首节点指向下一节点。

否则:

1. p初始指向头节点(索引0),用于找前驱

2. 循环找到待删除节点的前驱

3. 暂存待删除节点的地址(p的下一个节点)

4. 前驱节点的next跳过待删除节点,链接后续节点 

template<class T>
void chain<T>::erase(int theIndex)
{// Delete the element whose index is theIndex.// Throw illegalIndex exception if no such element.checkIndex(theIndex);// valid index, locate node with element to deletechainNode<T>* deleteNode;if (theIndex == 0){// remove first node from chaindeleteNode = firstNode;firstNode = firstNode->next;}else {  // use p to get to predecessor of desired nodechainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;deleteNode = p->next;p->next = p->next->next; // remove deleteNode from chain}listSize--;delete deleteNode;
}

方法insert:

若为首节点:firstNode = new chainNode<T>(theElement, firstNode);

非头部:单链表无法直接访问 “插入位置的前一个节点”(前驱),需从表头开始遍历 theIndex-1 次,定位到前驱节点 p—— 新节点必须插入在 p 和 p->next 之间(避免断链)。

template<class T>
void chain<T>::insert(int theIndex, const T& theElement)
{// Insert theElement so that its index is theIndex.if (theIndex < 0 || theIndex > listSize){// invalid indexostringstream s;s << "index = " << theIndex << " size = " << listSize;throw illegalIndex(s.str());}if (theIndex == 0)// insert at frontfirstNode = new chainNode<T>(theElement, firstNode);else{  // find predecessor of new elementchainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;// insert after pp->next = new chainNode<T>(theElement, p->next);}listSize++;
}

方法output与重载<<

template<class T>
void chain<T>::output(ostream& out) const
{// Put the list into the stream out.for (chainNode<T>* currentNode = firstNode;currentNode != NULL;currentNode = currentNode->next)out << currentNode->element << "  ";
}// overload <<
template <class T>
ostream& operator<<(ostream& out, const chain<T>& x){x.output(out); return out;}

chainWithIterator.h(迭代器)

// linked implementation of a linear list
// derives from abstract class linearList just to make sure
// all methods of the ADT are implemented
// unidirectional iterator for chain included#ifndef chain_
#define chain_#include <iostream>
#include <sstream>
#include <string>
#include "linearList.h"
#include "chainNode.h"
#include "myExceptions.h"using namespace std;class linkedDigraph;
template <class T> class linkedWDigraph;template<class T>
class chain : public linearList<T> 
{friend linkedDigraph;friend linkedWDigraph<int>;friend linkedWDigraph<float>;friend linkedWDigraph<double>;public:// constructor, copy constructor and destructorchain(int initialCapacity = 10);chain(const chain<T>&);~chain();// ADT methodsbool empty() const {return listSize == 0;}int size() const {return listSize;}T& get(int theIndex) const;int indexOf(const T& theElement) const;void erase(int theIndex);void insert(int theIndex, const T& theElement);void output(ostream& out) const;// iterators to start and end of listclass iterator;iterator begin() {return iterator(firstNode);}iterator end() {return iterator(NULL);}// iterator for chainclass iterator {public:// typedefs required by C++ for a forward iteratortypedef forward_iterator_tag iterator_category;typedef T value_type;typedef ptrdiff_t difference_type;typedef T* pointer;typedef T& reference;// constructoriterator(chainNode<T>* theNode = NULL){node = theNode;}// dereferencing operatorsT& operator*() const {return node->element;}T* operator->() const {return &node->element;}// incrementiterator& operator++()   // preincrement{node = node->next; return *this;}iterator operator++(int) // postincrement{iterator old = *this;node = node->next;return old;}// equality testingbool operator!=(const iterator right) const{return node != right.node;}bool operator==(const iterator right) const{return node == right.node;}protected:chainNode<T>* node;};  // end of iterator classprotected:void checkIndex(int theIndex) const;// throw illegalIndex if theIndex invalidchainNode<T>* firstNode;  // pointer to first node in chainint listSize;             // number of elements in list
};template<class T>
chain<T>::chain(int initialCapacity)
{// Constructor.if (initialCapacity < 1){ostringstream s;s << "Initial capacity = " << initialCapacity << " Must be > 0";throw illegalParameterValue(s.str());}firstNode = NULL;listSize = 0;
}template<class T>
chain<T>::chain(const chain<T>& theList)
{// Copy constructor.listSize = theList.listSize;if (listSize == 0){// theList is emptyfirstNode = NULL;return;}// non-empty listchainNode<T>* sourceNode = theList.firstNode;// node in theList to copy fromfirstNode = new chainNode<T>(sourceNode->element);// copy first element of theListsourceNode = sourceNode->next;chainNode<T>* targetNode = firstNode;// current last node in *thiswhile (sourceNode != NULL){// copy remaining elementstargetNode->next = new chainNode<T>(sourceNode->element);targetNode = targetNode->next;sourceNode = sourceNode->next;}targetNode->next = NULL; // end the chain
}template<class T>
chain<T>::~chain()
{// Chain destructor. Delete all nodes in chain.chainNode<T> *nextNode;while (firstNode != NULL){// delete firstNodenextNode = firstNode->next;delete firstNode;firstNode = nextNode;}
}template<class T>
void chain<T>::checkIndex(int theIndex) const
{// Verify that theIndex is between 0 and listSize - 1.if (theIndex < 0 || theIndex >= listSize){ostringstream s;s << "index = " << theIndex << " size = " << listSize;throw illegalIndex(s.str());}
}template<class T>
T& chain<T>::get(int theIndex) const
{// Return element whose index is theIndex.// Throw illegalIndex exception if no such element.checkIndex(theIndex);// move to desired nodechainNode<T>* currentNode = firstNode;for (int i = 0; i < theIndex; i++)currentNode = currentNode->next;return currentNode->element;
}template<class T>
int chain<T>::indexOf(const T& theElement) const
{// Return index of first occurrence of theElement.// Return -1 if theElement not in list.// search the chain for theElementchainNode<T>* currentNode = firstNode;int index = 0;  // index of currentNodewhile (currentNode != NULL && currentNode->element != theElement){// move to next nodecurrentNode = currentNode->next;index++;}// make sure we found matching elementif (currentNode == NULL)return -1;elsereturn index;
}template<class T>
void chain<T>::erase(int theIndex)
{// Delete the element whose index is theIndex.// Throw illegalIndex exception if no such element.checkIndex(theIndex);// valid index, locate node with element to deletechainNode<T>* deleteNode;if (theIndex == 0){// remove first node from chaindeleteNode = firstNode;firstNode = firstNode->next;}else {  // use p to get to predecessor of desired nodechainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;deleteNode = p->next;p->next = p->next->next; // remove deleteNode from chain}listSize--;delete deleteNode;
}template<class T>
void chain<T>::insert(int theIndex, const T& theElement)
{// Insert theElement so that its index is theIndex.if (theIndex < 0 || theIndex > listSize){// invalid indexostringstream s;s << "index = " << theIndex << " size = " << listSize;throw illegalIndex(s.str());}if (theIndex == 0)// insert at frontfirstNode = new chainNode<T>(theElement, firstNode);else{  // find predecessor of new elementchainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;// insert after pp->next = new chainNode<T>(theElement, p->next);}listSize++;
}template<class T>
void chain<T>::output(ostream& out) const
{// Put the list into the stream out.for (chainNode<T>* currentNode = firstNode;currentNode != NULL;currentNode = currentNode->next)out << currentNode->element << "  ";
}// overload <<
template <class T>
ostream& operator<<(ostream& out, const chain<T>& x){x.output(out); return out;}#endif

extendedLinearList.h(扩展类,增加清除所有元素和尾插方法)

// abstract class extendedLinearList
// extends linearList by adding functions to clear and append
// all methods are pure virtual functions#ifndef extendedLinearList_
#define extendedLinearList_
#include <iostream>
#include "linearList.h"using namespace std;template<class T>
class extendedLinearList : linearList<T> 
{public:virtual ~extendedLinearList() {}virtual void clear() = 0;// empty the listvirtual void push_back(const T& theElement) = 0;// insert theElement at end of list
};
#endif

extendedChain.h(增加lastNode数据成员)

// linked implementation of an extended linear list
// derives from abstract class extendedLinearList just to make sure
// all methods of the ADT are implemented
// unidirectional iterator for extendedChain included#ifndef extendedChain_
#define extendedChain_#include <iostream>
#include <sstream>
#include <string>
#include "extendedLinearList.h"
#include "chainWithIterator.h"
#include "myExceptions.h"using namespace std;template<class T>
class extendedChain : public extendedLinearList<T>, public chain<T> 
{public:// constructor and copy constructorextendedChain(int initialCapacity = 10) :chain<T>(initialCapacity) {}extendedChain(const extendedChain<T>& c) :chain<T>(c) {}// ADT methodsbool empty() const {return listSize == 0;}int size() const {return listSize;}T& get(int theIndex) const{return chain<T>::get(theIndex);}int indexOf(const T& theElement) const{return chain<T>::indexOf(theElement);}void erase(int theIndex);void insert(int theIndex, const T& theElement);void clear(){// Delete all nodes in chain.while (firstNode != NULL){// delete firstNodechainNode<T>* nextNode = firstNode->next;delete firstNode;firstNode = nextNode;}listSize = 0;}void push_back(const T& theElement);void output(ostream& out) const{chain<T>::output(out);}// additional methodvoid zero(){firstNode = NULL; listSize = 0;}protected:chainNode<T>* lastNode;  // pointer to last node in chain
};template<class T>
void extendedChain<T>::erase(int theIndex)
{// Delete the element whose index is theIndex.// Throw illegalIndex exception if no such element.checkIndex(theIndex);// valid index, locate node with element to deletechainNode<T>* deleteNode;if (theIndex == 0){// remove first node from chaindeleteNode = firstNode;firstNode = firstNode->next;}else {  // use p to get to predecessor of desired nodechainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;deleteNode = p->next;p->next = p->next->next; // remove deleteNode from chainif (deleteNode == lastNode)lastNode = p;}listSize--;delete deleteNode;
}template<class T>
void extendedChain<T>::insert(int theIndex, const T& theElement)
{// Insert theElement so that its index is theIndex.if (theIndex < 0 || theIndex > listSize){// invalid indexostringstream s;s << "index = " << theIndex << " size = " << listSize;throw illegalIndex(s.str());}if (theIndex == 0){// insert at frontfirstNode = new chainNode<T>(theElement, firstNode);if (listSize == 0)lastNode = firstNode;}else{  // find predecessor of new elementchainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;// insert after pp->next = new chainNode<T>(theElement, p->next);if (listSize == theIndex)lastNode = p->next;}listSize++;
}template<class T>
void extendedChain<T>::push_back(const T& theElement)
{// Insert theElement at the end of the chain.chainNode<T>* newNode = new chainNode<T>(theElement, NULL);if (firstNode == NULL)// chain is emptyfirstNode = lastNode = newNode;else{  // attach next to lastNodelastNode->next = newNode;lastNode = newNode;}listSize++;
}#endif

方法erase(增加了对lastNode的维护):

template<class T>
void extendedChain<T>::erase(int theIndex)
{// Delete the element whose index is theIndex.// Throw illegalIndex exception if no such element.checkIndex(theIndex);// valid index, locate node with element to deletechainNode<T>* deleteNode;if (theIndex == 0){// remove first node from chaindeleteNode = firstNode;firstNode = firstNode->next;}else {  // use p to get to predecessor of desired nodechainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;deleteNode = p->next;p->next = p->next->next; // remove deleteNode from chainif (deleteNode == lastNode)lastNode = p;}listSize--;delete deleteNode;
}

方法insert(增加了对lastNode的维护f'f):

template<class T>
void extendedChain<T>::insert(int theIndex, const T& theElement)
{// Insert theElement so that its index is theIndex.if (theIndex < 0 || theIndex > listSize){// invalid indexostringstream s;s << "index = " << theIndex << " size = " << listSize;throw illegalIndex(s.str());}if (theIndex == 0){// insert at frontfirstNode = new chainNode<T>(theElement, firstNode);if (listSize == 0)lastNode = firstNode;}else{  // find predecessor of new elementchainNode<T>* p = firstNode;for (int i = 0; i < theIndex - 1; i++)p = p->next;// insert after pp->next = new chainNode<T>(theElement, p->next);if (listSize == theIndex)lastNode = p->next;}listSize++;
}

方法push_back:

  1. 创建新节点:元素为 theElementnext 为 NULL(确保是尾部节点);
  2. 分场景接入:
    • 空链表:firstNode 和 lastNode 同时指向新节点;
    • 非空链表:先将新节点接在当前 lastNode 后,再更新 lastNode 为新节点;
  3. 更新长度:listSize++,同步链表状态。
template<class T>
void extendedChain<T>::push_back(const T& theElement)
{// Insert theElement at the end of the chain.chainNode<T>* newNode = new chainNode<T>(theElement, NULL);if (firstNode == NULL)// chain is emptyfirstNode = lastNode = newNode;else{  // attach next to lastNodelastNode->next = newNode;lastNode = newNode;}listSize++;
}

二、部分习题及解答

2,3,4,5

template<class T>
void chain<T>::setSize(int theSize) {if (theSize < 0) { // 大小不能为负ostringstream s;s << "Size = " << theSize << " must be >= 0";throw illegalParameterValue(s.str());}// 原大小 > 目标大小时,删除末尾多余元素while (listSize > theSize) {erase(listSize - 1); // 从最后一个元素开始删}
}
template<class T>
void chain<T>::set(int theIndex, const T& theElement) {checkIndex(theIndex); // 检查索引是否在 [0, listSize-1]chainNode<T>* current = firstNode;for (int i = 0; i < theIndex; ++i) { // 找到目标节点current = current->next;}current->element = theElement; // 替换元素
}

4.删除一定范围节点

template<class T>
void chain<T>::removeRange(int fromIndex, int toIndex) {// 检查索引合法性if (fromIndex < 0 || toIndex >= listSize || fromIndex > toIndex) {ostringstream s;s << "Invalid range: from=" << fromIndex << ", to=" << toIndex << ", size=" << listSize;throw illegalIndex(s.str());}chainNode<T>* prev = NULL;chainNode<T>* curr = firstNode;// 找到fromIndex的前驱节点for (int i = 0; i < fromIndex; ++i) {prev = curr;curr = curr->next;}// 批量删除[fromIndex, toIndex]的节点int count = toIndex - fromIndex + 1;chainNode<T>* next;for (int i = 0; i < count; ++i) {next = curr->next;delete curr;curr = next;}// 重新连接链表(处理头节点特殊情况)if (prev == NULL) {firstNode = curr;} else {prev->next = curr;}listSize -= count;
}
template<class T>
int chain<T>::lastIndexOf(const T& theElement) const {int lastIdx = -1;chainNode<T>* curr = firstNode;int idx = 0;while (curr != NULL) {if (curr->element == theElement) {lastIdx = idx; // 记录最后一次匹配的索引}curr = curr->next;idx++;}return lastIdx;
}

6,7,8,9

template<class T>
T& chain<T>::operator[](int theIndex) {checkIndex(theIndex); // 复用已有索引检查,非法则抛 illegalIndexchainNode<T>* curr = firstNode;for (int i = 0; i < theIndex; ++i) {curr = curr->next;}return curr->element; // 返回元素引用,支持读写
}template<class T>
const T& chain<T>::operator[](int theIndex) const {checkIndex(theIndex);chainNode<T>* curr = firstNode;for (int i = 0; i < theIndex; ++i) {curr = curr->next;}return curr->element; // 常量版本,仅支持读
}
template <class T>
bool operator==(const chain<T>& x, const chain<T>& y) {if (x.listSize != y.listSize) return false; // 长度不同直接不相等chainNode<T>* nodeX = x.firstNode;chainNode<T>* nodeY = y.firstNode;while (nodeX != nullptr) {if (nodeX->element != nodeY->element) return false; // 元素不同则不相等nodeX = nodeX->next;nodeY = nodeY->next;}return true; // 所有元素都相等
}
template <class T>
bool operator!=(const chain<T>& x, const chain<T>& y) {return !(x == y); // 直接复用 == 的结果取反
}
template <class T>
bool operator<(const chain<T>& x, const chain<T>& y) {chainNode<T>* nodeX = x.firstNode;chainNode<T>* nodeY = y.firstNode;while (nodeX != nullptr && nodeY != nullptr) {if (nodeX->element < nodeY->element) return true;  // x的元素更小,返回trueif (nodeX->element > nodeY->element) return false; // x的元素更大,返回falsenodeX = nodeX->next; // 元素相等,继续比较下一个nodeY = nodeY->next;}// 前缀都相等,x已空但y还有元素 → x更小;否则(都空或y空)→ x不更小return (nodeX == nullptr && nodeY != nullptr);
}

10,11,12

template<class T>
void chain<T>::swap(chain<T>& theChain) {// 交换头节点指针chainNode<T>* tempNode = firstNode;firstNode = theChain.firstNode;theChain.firstNode = tempNode;// 交换链表长度int tempSize = listSize;listSize = theChain.listSize;theChain.listSize = tempSize;
}
template<class T>
chain<T> arrayListToChain(const arrayList<T>& arrList) {chain<T> result;int n = arrList.size();for (int i = 0; i < n; ++i) {result.insert(i, arrList.get(i));}return result;
}
template<class T>
arrayList<T> chainToArray1(const chain<T>& ch) {arrayList<T> result;int n = ch.size();for (int i = 0; i < n; ++i) {result.insert(i, ch.get(i));}return result;
}
template<class T>
arrayList<T> chainToArray2(const chain<T>& ch) {arrayList<T> result;typename chain<T>::iterator it = ch.begin();int i = 0;while (it != ch.end()) {result.insert(i++, *it);++it;}return result;
}

13.

 // 1. fromList:将数组线性表 theList 转换为当前链表void fromList(const arrayList<T>& theList) {// 先清空当前链表(删除所有现有元素)while (!empty()) {erase(0);}int n = theList.size(); // 数组线性表的元素个数for (int i = 0; i < n; ++i) {insert(i, theList.get(i)); // 逐个插入数组元素到链表}}// 2. toList:将当前链表转换为数组线性表 theListvoid toList(arrayList<T>& theList) const {// 先清空目标数组线性表while (!theList.empty()) {theList.erase(0);}int n = listSize; // 当前链表的元素个数for (int i = 0; i < n; ++i) {theList.insert(i, get(i)); // 逐个获取链表元素插入到数组}}

14.

template <class T>
inline void chain<T>::leftShift(int i)
{if (i < 0 || i > listSize) {ostringstream s;s << "左移位数 i = " << i << " 无效,链表当前大小为 " << listSize;throw illegalIndex(s.str());}for (int j = 0; j < i; ++j) {erase(0);}
}

15,16

template<class T>
void chain<T>::reverse() {if (listSize <= 1) return; // 空或单元素链表无需反转chainNode<T>* prev = NULL;   // 前一个节点(初始为NULL,对应新尾节点)chainNode<T>* curr = firstNode; // 当前节点chainNode<T>* next;          // 下一个节点的临时存储while (curr != NULL) {next = curr->next;      // 保存下一个节点curr->next = prev;      // 反转当前节点的next指针prev = curr;            // 移动prev到当前节点curr = next;            // 移动curr到下一个节点}firstNode = prev; // 最后prev指向原链表的尾节点,作为新的头节点
}

16:新建一个空链表,从原链表尾部向头部依次取元素插入新链表头部,最后复制新链表到原链表。

template<class T>
void reverseChain(chain<T>& c) {chain<T> temp;int n = c.size();// 从原链表最后一个元素开始,依次插入到temp的头部for (int i = n - 1; i >= 0; --i) {temp.insert(0, c.get(i));}// 清空原链表并复制temp的内容while (!c.empty()) {c.erase(0);}for (int i = 0; i < n; ++i) {c.insert(i, temp.get(i));}
}

17,18

template <class T>
extendedChain<T> meld(const extendedChain<T>& a, const extendedChain<T>& b) {extendedChain<T> c;int i = 0, j = 0;bool takeA = true;while (i < a.size() || j < b.size()) {if (takeA && i < a.size()) {c.insert(c.size(), a.get(i)); // 取a的元素,插入到c末尾i++;} else if (j < b.size()) {c.insert(c.size(), b.get(j)); // 取b的元素,插入到c末尾j++;}takeA = !takeA; // 切换取a/b的标记}return c;
}
template <class T>
void chain<T>::meld(chain<T>& a, chain<T>& b) {// 清空当前链表while (!empty()) erase(0);chainNode<T> *currA = a.firstNode, *currB = b.firstNode;chainNode<T> *prev = nullptr, *newNode;bool takeA = true;// 交替拼接a和b的节点while (currA || currB) {if (takeA && currA) {newNode = currA;currA = currA->next;} else if (currB) {newNode = currB;currB = currB->next;} else break;if (!prev) firstNode = newNode; // 处理第一个节点else prev->next = newNode;prev = newNode;takeA = !takeA;}// 拼接剩余节点(若a或b还有剩余)prev->next = currA ? currA : currB;// 更新长度 & 置空a、blistSize = a.listSize + b.listSize;a.firstNode = b.firstNode = nullptr;a.listSize = b.listSize = 0;
}

19,20

类似 “归并排序” 的合并阶段:同时遍历两个有序链表,每次选较小的元素插入新链表,最后拼接剩余元素。

template <class T>
extendedChain<T> merge(const extendedChain<T>& a, const extendedChain<T>& b) {extendedChain<T> c;int i = 0, j = 0;// 同时遍历a和b,选较小元素插入cwhile (i < a.size() && j < b.size()) {if (a.get(i) < b.get(j)) {c.insert(c.size(), a.get(i++));} else {c.insert(c.size(), b.get(j++));}}// 拼接a的剩余元素while (i < a.size()) c.insert(c.size(), a.get(i++));// 拼接b的剩余元素while (j < b.size()) c.insert(c.size(), b.get(j++));return c;
}

直接操作节点指针,交替 “摘取”a/b 的节点拼接到当前链表,合并后清空 a 和 b

template <class T>
void chain<T>::merge(chain<T>& a, chain<T>& b) {while (!empty()) erase(0); // 清空当前链表chainNode<T> *currA = a.firstNode, *currB = b.firstNode, *prev = nullptr;while (currA && currB) {chainNode<T>* node;// 选较小的节点if (currA->element < currB->element) {node = currA;currA = currA->next;} else {node = currB;currB = currB->next;}// 接入当前链表if (!prev) firstNode = node;else prev->next = node;prev = node;node->next = nullptr;}// 拼接剩余节点prev->next = currA ? currA : currB;// 更新长度并清空a、blistSize = a.listSize + b.listSize;a.firstNode = b.firstNode = nullptr;a.listSize = b.listSize = 0;
}

21,22

第 21 题:非成员方法 split(复制元素生成新链表)

实现逻辑

遍历原链表 c,按索引奇偶性,将元素分别复制到新链表 a(奇数索引)和 b(偶数索引),不修改原链表 c

template <class T>
void split(extendedChain<T>& a, extendedChain<T>& b, const extendedChain<T>& c) {// 清空a和b,避免原有元素干扰while (!a.empty()) a.erase(0);while (!b.empty()) b.erase(0);int n = c.size();for (int i = 0; i < n; ++i) {if (i % 2 == 1) { // 奇数索引(从0开始),放入aa.insert(a.size(), c.get(i));} else { // 偶数索引,放入bb.insert(b.size(), c.get(i));}}
}

第 22 题:成员方法 chain<T>::split(复用原节点生成链表)

实现逻辑

直接操作原链表(*this)的节点,拆分到 a 和 b,拆分后原链表被清空(节点 “转移” 到 ab)。

template <class T>
void chain<T>::split(chain<T>& a, chain<T>& b) {// 1. 清空目标链表a和b(避免原有元素干扰)while (!a.empty()) a.erase(0);while (!b.empty()) b.erase(0);chainNode<T> *curr = firstNode;   // 指向当前链表的当前节点chainNode<T> *aTail = nullptr;    // 记录a的尾节点(用于拼接)chainNode<T> *bTail = nullptr;    // 记录b的尾节点int index = 0;                    // 当前元素的索引(从0开始)// 2. 遍历当前链表的所有节点while (curr != nullptr) {chainNode<T> *next = curr->next; // 暂存下一个节点(防止断链后丢失)curr->next = nullptr;           // 断开当前节点与原链表的连接// 3. 根据索引奇偶性,将节点加入a或bif (index % 2 == 1) { // 奇数索引 → 加入aif (a.empty()) {  // a为空时,设置a的头节点a.firstNode = curr;aTail = curr;} else {          // a非空时,拼到a的尾部aTail->next = curr;aTail = curr;}a.listSize++;     // 更新a的长度} else {              // 偶数索引 → 加入bif (b.empty()) {  // b为空时,设置b的头节点b.firstNode = curr;bTail = curr;} else {          // b非空时,拼到b的尾部bTail->next = curr;bTail = curr;}b.listSize++;     // 更新b的长度}curr = next;  // 移动到原链表的下一个节点index++;      // 索引+1}// 4. 清空当前链表(*this)firstNode = nullptr;listSize = 0;
}

23.

要实现循环右移操作,核心思路是找到 “断点” 节点,将链表拆分为两部分后重新连接。

循环右移 i 位 = 把链表的后 i 个元素 “搬到最前面”,剩下的前半部分接在后面。

template <class T>
void extendedChain<T>::circularShift(int i) {int n = listSize;if (n <= 1) return; // 空链表或单元素,无需移动// 处理i的范围:取模转为有效偏移(0 ≤ i < n)i = i % n;if (i < 0) i += n;if (i == 0) return; // 偏移0,无需操作// 步骤1:找到第 n-i 个节点(它的下一个节点将成为新头)chainNode<T>* prev = firstNode;for (int j = 0; j < n - i - 1; ++j) {prev = prev->next;}// 步骤2:记录新头、原尾,并重组链表chainNode<T>* newFirst = prev->next; // 新头是第 n-i 个节点的下一个chainNode<T>* tail = newFirst;       // 找原链表的尾节点while (tail->next != nullptr) {tail = tail->next;}tail->next = firstNode; // 原尾连原头,形成临时循环prev->next = nullptr;   // 断开原链表,新头的前驱置空firstNode = newFirst;   // 更新头节点
}

http://www.dtcms.com/a/466896.html

相关文章:

  • PTA6-11 拆分实数的整数与小数部分(C)
  • 重庆工业网站建设黄冈做网站价格
  • 行政单位门户网站建设方案惠州公众号开发公司
  • 有网络网站打不开自建网站需要哪些技术
  • 建设工程材料网站江西省宜春市建设局网站
  • 网站seo优化徐州百度网络网站的中英文翻译是怎么做的
  • 【LeetCode】61. 旋转链表
  • 整站seo优化哪家好电商设计网站培训
  • 【GD32】启动过程-程序计数器(PC)
  • 茶艺实训室:为学习者打造专业茶艺实操平台
  • 机械设计网站推荐贵州建设监理网站培训通知栏
  • 常州网站制作策划手机制作网站主页软件
  • 淘宝天猫优惠券网站怎么做工作啦
  • H3C 实现ACL 访问控制
  • 【北京迅为】iTOP-4412精英版使用手册-第三十七章 Hello_Driver_Module
  • 1 建设好自媒体门户网站网站备案要几天
  • GESP C++等级认证三级13-操作string2-2
  • 富连网网站开发数字营销成功案例
  • 我的网站 dedecms网站开发模式分为
  • 【附代码】Jupyter 多进程调用 seaborn 并保留格式
  • 正规手机网站建设平台之梦一个系统做多个网站
  • 服务器数据恢复—Raid5多盘掉线,存储如何“起死回生”?
  • 郑州网站推广价vue.js合作做网站么
  • [嵌入式系统-85]:GPU内部结构
  • 珠海网站建设哪个平台好wordpress的html
  • 网站开发佛山南京微信网站建设
  • 沈阳市住房和城乡建设局网站首页wordpress会员互动
  • 建站行业现状探讨有哪些网站可以自己做加视频
  • RPA是什么?企业如何借助有赞平台实现订单与会员自动化
  • cpp03:小项目Da