作业1
在示例的基础上,实现如下功能:
- 链表添加节点功能
- bool addNode(list* plist,int nVal);
- 参数:plist,要追加节点的链表指针,nVal,节点值
- 返回值:是否成功
- 要求内部有合法性验证
- 节点添加于链表尾部
- 链表删除节点功能
- bool delNode(list* plist);
- 参数:plist,链表指针
- 返回值:是否成功
- 要求内部有合法性验证
- 删除尾部节点
- 链表遍历功能
- void traverse(list* plist,int nDir);
- 参数:plist,链表指针,nDir,遍历方向:0-正向,1-反向
- 要求内部有合法性验证
- 遍历时打印每个节点值
- 链表保存到文件
- void savelist(list* plist);
- 参数:plist,链表指针
- 要求内部有合法性验证
- 仅保存节点值,保存的数据文件是1列多行,数据文件名为data.txt
- 从数据文件读取数据并创建链表
- void readlist(list* plist);
- 参数:plist,链表指针
- 数据文件名称默认为data.txt,若文件中包含有效数据,则创建链表,依次读出每个节点的值,并添加到链表中;否则返回。
- (附加,可选做)节点删除功能(指定索引)
- bool delNode(list* plist,int nIdx);
- 参数:plist,链表指针,nIdx,要删除的节点索引
- 返回值:是否成功
- 要求内部有合法性验证
- 头节点索引认为是0,依次增加
- (附加,可选做)节点插入功能(指定索引)
- bool insertNode(list* plist,int nVal,int nIdx);
- 参数:plist,链表指针,nVal,节点值,nIdx,节点插入索引
- 返回值:是否成功
- 要求内部有合法性验证
- 头节点索引认为是0,依次增加。若指定位置不合法,则返回false。
// 22309132作业1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
typedef struct LNode {
int data;
struct LNode* next; //定义一个LNode的指针
struct LNode* prior;
}LNode;
LNode* InitList(LNode* L) {//初始化双链表
L = (LNode*)malloc(sizeof(LNode));
L->prior = NULL;
L->next = NULL;
return L;
}
bool addNode(LNode* plist, int nVal) {
LNode* p = plist;
while ((p->next)!=NULL) //寻找尾结点
{
p = p->next;
}
LNode* L = (LNode*)malloc(sizeof(LNode));
L->data = nVal;
L->prior = p;
p->next = L;
p = L; //p重新指向尾结点
p->next = NULL;
if (((p->data) == nVal) && ((p->next) == NULL)&&((p->prior)!=NULL))
return true;
else
{
return false;
}
}
bool delNode(LNode* plist) {
LNode* p = plist;
while ((p->next->next) != NULL) //寻找尾结点的前一个结点
{
p = p->next;
}
p->next = NULL; //删除尾结点
free(p->next);//释放内存
if ((p != NULL) && ((p->next) == NULL)) {
return true;
}
else
{
return false;
}
}
void traverse(LNode* plist, int nDir) {
LNode* pl = plist;
// LNode* p = pl->next;
if (nDir == 0) {
while ((pl->next)!=NULL)
{
cout << pl->next->data << endl;
pl = pl->next;
}
}
else if(nDir == 1){
while ((pl->next)!=NULL) //寻找尾结点
{
pl = pl->next;
}
while ((pl->prior)!=NULL)
{
cout << pl->data << endl;
pl = pl->prior;
}
}
}
void savelist(LNode* plist) {
LNode* p = plist;
ofstream fin;
fin.open("data.txt");
while ((p->next) != NULL) {
if ((p->next->next)==NULL)
{
fin << p->next->data;
}
else
{
fin << p->next->data << endl;
}
p = p->next;
}
}
void readlist(LNode* plist) {
LNode* p = plist;
ifstream infile("data.txt", ios::in);
if (!infile) {
cout << "文件打开失败!" << endl;
return;
}
while (infile)
{
int data;
if (!(infile >> data)) {
break; // break if read was unsuccessful
}
LNode* L = (LNode*)malloc(sizeof(LNode));
L->data = data;
p->next = L;
L->prior = p;
L->next = nullptr;
p = L;
}
}
bool delNode(LNode* plist, int index) {
// 如果链表为空
if (plist == NULL || index < 0) {
cout << "链表为空" << endl;
return false;
}
LNode* current = plist;
int count = 0;//头结点索引是0(头结点不存储数据)
// 找到要删除的节点
while (current != NULL && count < index) {
current = current->next;
count++;
}
// 如果找不到要删除的节点
if (current == NULL) {
cout << "can not found node!" << endl;
return false;
}
// 如果节点是头节点
if (current->prior == NULL) {
plist = current->next;
if (current->next != NULL) {
current->next->prior = NULL;
}
}
// 如果节点是尾节点
else if (current->next == NULL) {
current->prior->next = NULL;
}
// 如果节点在链表中间
else {
current->prior->next = current->next;
current->next->prior = current->prior;
}
free(current);
return true;
}
bool insertNode(LNode* plist, int nVal, int nIdx) {
LNode* newNode = (LNode*)malloc(sizeof(LNode));
newNode->data = nVal;
LNode* current = plist;
int count = 0;
// 找到指定索引位置的节点
while (current != NULL && count < nIdx) {
current = current->next;
count++;
}
// 如果找到了指定的位置
if (current != NULL) {
newNode->next = current;
newNode->prior = current->prior;
current->prior->next = newNode;
current->prior = newNode;
return true; // 插入成功
}
else {
cout << "插入失败" << endl;
return false; // 插入失败
}
}
int main()
{
LNode* Plist=nullptr;
Plist = InitList(Plist);
//1.随机生成10个整型数,并逐一添加到链表中
LNode* p = Plist;
srand(time(0));
for (int i = 0; i < 10; i++)
{
addNode(Plist, (int)rand());
}
// traverse(Plist, 0);//测试
//2. 删除结点
delNode(Plist);
// traverse(Plist, 0);//测试
//3. 删除节点(指定索引)
delNode(Plist, 1);
// traverse(Plist, 0);//测试
//4. 追加节点
addNode(Plist, 66);
// traverse(Plist, 0);//测试
//5. 追加节点(指定索引)
insertNode(Plist, 666, 5);
//6. 遍历当前链表
traverse(Plist, 0);
traverse(Plist, 1);
//7. 保存链表到数据文件
savelist(Plist);
//8. 读取数据文件,并遍历
LNode* Plist1 = nullptr;
Plist1 = InitList(Plist1);
readlist(Plist1);
traverse(Plist1, 0);
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件