如何实现带计数字段的链表复制函数并返回新链表头指针?
嘿,我来帮你搞定这个带count字段的链表复制问题!首先咱们先捋捋你现有代码里的几个关键bug(这些会导致程序跑不起来或者行为异常),然后再实现链表复制的核心功能。
现有代码的主要问题
- 构造函数逻辑错误:你的
set类构造函数里一开始就遍历delete节点,但此时head是NULL,这个循环完全没必要,反而容易触发未定义行为,应该只初始化head为NULL即可。 - isLast函数空指针问题:
last指针没有初始化就直接访问last->next,会导致程序崩溃,正确做法是先遍历到链表末尾再判断。 - insert函数链接缺失:插入新节点时,你创建了新节点但没有把它链接到原链表的末尾,需要先找到最后一个节点再完成链接。
- deleteLast函数语法错误:
Snode *current= new head;是非法写法,应该直接用Snode *current = head;,而且不需要用new创建previous指针。 - count函数逻辑混乱:循环里每次都会输出内容,不管有没有找到目标字符,而且最后返回
temp->count时temp可能已经是NULL,会导致崩溃。 - remove函数赋值错误:
while(current->next=NULL)是赋值操作而非判断,应该改成while(current->next != NULL),而且参数temp的作用不明确,应该从head开始遍历找目标节点。
实现链表复制函数
要复制整个链表到新内存,我们需要遍历原链表的每个节点,为每个节点分配新的内存空间,复制data和count字段,再把这些新节点依次链接起来,最后返回新链表的头节点。因为head是set类的私有成员,所以我们在类中添加一个成员函数来实现这个功能最合理。
修正后的完整代码(包含复制功能)
#include <iostream> using namespace std; struct Snode { char data; int count = 1; Snode *next = NULL; Snode(char a) : data(a) {} }; class set { private: Snode *head; public: // 修正构造函数:仅初始化head为NULL set() : head(NULL) {} // 析构函数保持正常逻辑 ~set() { Snode *temp = head; while (temp != NULL) { head = head->next; delete temp; temp = head; } } bool isAvailable(char value) { Snode *temp = head; while (temp != NULL) { if (temp->data == value) return true; temp = temp->next; } return false; } bool isFirst(char value) { if (head == NULL) return false; return (head->data == value); } // 修正isLast函数 bool isLast(char value) { if (head == NULL) return false; Snode *last = head; while (last->next != NULL) { last = last->next; } return (last->data == value); } void display() { Snode *temp = head; while (temp != NULL) { cout << temp->data << " " << temp->count << "\n"; temp = temp->next; } } // 修正insert函数:补全新节点链接逻辑 void insert(char value) { if (head == NULL) { Snode *temp = new Snode(value); temp->count = 1; head = temp; } else { if (isAvailable(value)) { Snode *temp = head; while (temp->data != value) temp = temp->next; temp->count += 1; } else { Snode *temp = new Snode(value); temp->count = 1; temp->next = NULL; // 找到原链表最后一个节点 Snode *last = head; while (last->next != NULL) { last = last->next; } last->next = temp; } } } // 修正count函数 int count(char value) { Snode *temp = head; while (temp != NULL) { if (temp->data == value) { cout << temp->count << endl; return temp->count; } temp = temp->next; } cout << "This character is not in the list" << endl; return -1; // 返回-1标记未找到 } void deleteFirst() { if (head == NULL) return; Snode *temp = head; head = head->next; delete temp; } // 修正deleteLast函数 void deleteLast() { if (head == NULL) return; // 处理只有一个节点的情况 if (head->next == NULL) { delete head; head = NULL; return; } Snode *current = head; Snode *previous = NULL; while (current->next != NULL) { previous = current; current = current->next; } previous->next = NULL; delete current; } // 修正remove函数 void remove(char value) { if (!isAvailable(value)) { cout << "Not available" << endl; return; } Snode *temp = head; Snode *prev = NULL; // 定位目标节点 while (temp != NULL && temp->data != value) { prev = temp; temp = temp->next; } if (temp->count == 1) { if (isFirst(value)) { deleteFirst(); } else if (isLast(value)) { deleteLast(); } else { prev->next = temp->next; delete temp; } } else { temp->count--; } } // 新增:复制链表到新内存,返回新链表头节点 Snode* copyLinkedList() { if (head == NULL) { return NULL; // 原链表为空,直接返回NULL } // 创建新链表的头节点 Snode *newHead = new Snode(head->data); newHead->count = head->count; Snode *currentOriginal = head->next; Snode *currentNew = newHead; // 遍历原链表,逐个复制节点 while (currentOriginal != NULL) { Snode *newNode = new Snode(currentOriginal->data); newNode->count = currentOriginal->count; // 链接到新链表末尾 currentNew->next = newNode; // 移动指针继续遍历 currentNew = newNode; currentOriginal = currentOriginal->next; } currentNew->next = NULL; // 新链表末尾置空,保证结构正确 return newHead; } // 静态工具函数:打印复制后的链表(用于测试) static void printCopiedList(Snode *head) { Snode *temp = head; while (temp != NULL) { cout << temp->data << " " << temp->count << "\n"; temp = temp->next; } } }; int main() { set mySet; mySet.insert('c'); mySet.insert('a'); mySet.insert('a'); mySet.insert('c'); mySet.insert('c'); cout << "原链表内容:" << endl; mySet.display(); // 复制链表 Snode *copiedHead = mySet.copyLinkedList(); cout << "\n复制后的链表内容:" << endl; set::printCopiedList(copiedHead); // 手动释放复制后的链表内存,避免内存泄漏 Snode *temp = copiedHead; while (temp != NULL) { Snode *next = temp->next; delete temp; temp = next; } return 0; }
复制函数核心逻辑说明
- 空链表判断:如果原链表为空,直接返回NULL,避免无效操作。
- 创建新头节点:为原链表的头节点分配新内存,复制
data和count字段。 - 遍历复制节点:用两个指针分别遍历原链表和新链表,为每个原节点创建对应的新节点,复制数据后链接到新链表末尾。
- 末尾置空:新链表最后一个节点的
next设为NULL,保证链表结构完整。 - 内存释放:使用完复制后的链表后,要手动释放其内存,避免内存泄漏。
这样得到的新链表完全独立于原链表,修改任意一方都不会影响另一方,所有节点都在新的内存区域。
内容的提问来源于stack exchange,提问作者nitwit
相关产品推荐
相关产品推荐

