有时候为了方便自测,自用,想要把接口做一些小改变(涉及输入输出),亦或是想要方便归档整理,我们会自己使用IDE编写代码来刷题。
一般一种类型的题目,比如链表,我们可以放在一个工程下面。但是刷的题多了,很容易就会混乱,这时候需要良好的代码结构来进行梳理。
代码结构
以链表为例,一个链表类型题的工程应包含:构建链表的头文件:listNode.h,主函数源文件:main.cpp,各个题目对应一组的头文件和源文件

构建链表的头文件:listNode.h
这个文件主要包含一个结构体 ListNode 用于构建链表的一个节点,以及一个函数 createListNode 用于通过 vector 容器构建一个链表,代码如下:
#ifndef LISTNODE_LISTNODE
#define LISTNODE_LISTNODE
#include<iostream>
#include<vector>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
ListNode() : val(0), next(NULL) {}
ListNode(int x) : val(x), next(NULL) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
void printListNode()
{
cout << val << " ";
ListNode* head = next;
while (head)
{
cout << head->val << " ";
head = head->next;
}
cout << endl;
}
};
template<class T>
ListNode* createListNode(vector<T> data)
{
ListNode* head;
head = new ListNode(data[0]);
ListNode* tempPtr;
tempPtr = head;
for (unsigned int i = 1; i < data.size(); ++i)
{
ListNode* tempNode;
tempNode = new ListNode(data[i]);
tempPtr->next = tempNode;
tempPtr = tempPtr->next;
}
return head;
}
#endif
为了方便输出整个链表,我在 ListNode 增加了一个函数作为结构体成员,用于输出整个链表的值
目前这个链表只支持 int 型,后面有需要再套个模板类以适应不同的类型
各个题目对应一组的头文件和源文件
这里以链表中的节点每k个一组翻转为例
头文件为 ReverseKGroup.h, 对应的源文件为 ReverseKGroup.cpp,源码如下:
#ifndef LISTNODE_REVERSEKGROUP
#define LISTNODE_REVERSEKGROUP
#include"listNode.h"
using namespace std;
/*
将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
数据范围: 2000 0≤n≤2000 , 1≤k≤2000 ,链表中每个元素都满足 0≤val≤1000
要求空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
例如:
给定的链表是 1→2→3→4→5
对于 k = 2k=2 , 你应该返回 2→1→4→3→5
对于 k = 3k=3 , 你应该返回 3→2→1→4→5
*/
class ReverseKGroup
{
public:
bool integralLN = true;
ListNode* endNode = nullptr;
ListNode* tempHead = nullptr;
ListNode* reverseKGroup(ListNode* head, int k);
ListNode* reverse(ListNode* head, int n);
};
#endif
#include "ReverseKGroup.h"
ListNode* ReverseKGroup::reverseKGroup(ListNode* head, int k)
{
if (head == nullptr || k == 1) return head;
head = reverse(head, k);
while (integralLN)
{
ListNode* concatHead = tempHead;
ListNode* tempPointer = endNode; // 下一段反转的起点
tempPointer = reverse(tempPointer, k);
if (integralLN) concatHead->next = tempPointer; // 上一段和这一段拼接
}
return head;
}
ListNode* ReverseKGroup::reverse(ListNode* head, int n)
{
if (head == nullptr)
{
integralLN = false;
return head;
}
if (n == 1)
{
endNode = head->next;
return head;
}
ListNode* node = reverse(head->next, n - 1);
if (integralLN)
{
head->next->next = head;
head->next = endNode;
tempHead = head; // 用于下一段拼接的头
return node;
}
else
{
return head;
}
}
头文件用于inlcude需要的头文件,描述题目内容,方便复习,声明用来解题的类
源文件就拿来写解题用的代码,这部分跟浏览器里用 leetcode 一类的题库提供的集成环境差不多,但debug起来可方便太多了
主函数源文件:main.cpp
主函数源文件用于创建测试用例,并执行测试程序,代码如下:
// listNode.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <vector>
#include "listNode.h"
#include "ReverseListRecursion.h"
#include "ReverseKGroup.h"
#include "ReverseBetween.h"
#include "merge.h"
using namespace std;
int main()
{
vector<int> inputData = { 1, 2, 3, 4, 5 ,6, 7 };
vector<int> inputData_2 = { 3, 4, 5 ,6, 7, 8, 9 };
ListNode* head = createListNode<int>(inputData);
ListNode* head_2 = createListNode<int>(inputData_2);
ListNode* printHead = head;
ListNode* printHead_2 = head_2;
head->printListNode();
head_2->printListNode();
//ReverseListRecursion reverse;
//head = reverse.tureReturn(head);
//head->printListNode();
//ReverseBetween reverse;
//head = reverse.reverseBetween(head, 2, 4);
//head->printListNode();
ReverseKGroup reverse;
head = reverse.reverseKGroup(head, 3);
head->printListNode();
//MergeListNode merge;
//ListNode* newHead = merge.merge(head, head_2);
//newHead->printListNode();
return 0;
}
这样的代码结构比较简洁,逻辑清晰,各个题目互不干扰,并且可以很方便地进行归档整理,一道题就对应一组头文件和源文件,复习起来也很方便。
本文介绍了一种组织链表算法题解的有效方法,包括代码结构的设计思路,如何创建链表节点,实现特定链表操作(如节点翻转),以及如何构建测试用例。

被折叠的 条评论
为什么被折叠?



