C++单链表增、删、插、改、查(基础版)

这里分了四部分,不喜欢一堆堆代码挤在一起的,开了个项目写的这些代码,我觉得是很通俗易懂的那种代码了,具体链表实现的讲解,以及对指针的运用,请移步各大教学视频/文档
代码的具体解释请看注释哟~

这里以下面代码的删除和插入为例,画了个图(也不知道够不够生动形象……我自己做的时候,就这么画的整理思路的)建议看完代码再回来看这个
1.List.h

#ifndef LIST_H_
#define LIST_H_

const int size = 40;
//数据域
struct Data
{
	char name[size];
	int account;
};
//结点
struct Node
{
	Data data;
	Node *next;
};
//管理结点的类
class NodeManager
{
	private:
		int length;
		Node headNode;
	public:
		NodeManager();//对头节点进行初始化
		void addNode(Node *newNode);//添加结点
		int findIndex(const char *name);
		void removeNode(const char *name);//删除结点
		Node* findNode(const char *_name);
		void insertNode(const char *_name, Node *newNode);//插入结点
		void updateNode(const char *oldName, char *newName, double acc);//修改节点
		void showNode() const;//查看结点
};

//这里是我嫌弃一堆堆的代码出现在main函数里加的
void Add(NodeManager* manager);
void Remove(NodeManager* manager);
void Insert(NodeManager* manager);
void Update(NodeManager* manager);

#endif

2.List.cpp

#include<iostream>
#include<cstring>
#include"list.h"

NodeManager::NodeManager()
{
	strcpy(headNode.data.name, "");
	headNode.data.account = 0.0;
	headNode.next = NULL;
	length = 0;
}

void NodeManager::addNode(Node *newNode)
{
	if(headNode.next==NULL)
		headNode.next = newNode;
	else
	{
	//创建临时结点去遍历
		Node *temp = headNode.next;
		while(temp->next!=NULL)
			temp = temp->next;
	//直到遍历到最后一个,也就是temp->next==NULL
		temp->next = newNode;
		newNode->next = NULL;
	}
	++length;
}
//为了提供方便(虽然现在只有删除用到了下标,但是以防万一,这是用来找对应的名字的对象的下标的)
int NodeManager::findIndex(const char *_name)
{
	Node *temp = headNode.next;//从头节点的指针开始找
	int index = 0;
	while(temp!=NULL)//注意这里是temp,而不是temp->next
	{
		if(strcmp(temp->data.name, _name)==0)
			return index;
		else
		{
			++index;
			temp = temp->next;
		}
	}
	//temp==NULL
	std::cout << "This guy's not on the list!\n";
	return -1;//因为前面有可能index=0,所以这里得是负数了
}

void NodeManager::removeNode(const char *_name)
{//这个有图解
	int index = findIndex(_name);
	if(index==-1)
		return;
	else
	{
		Node *temp = &headNode;//要注意这里是头节点
		int s_index = 0;//开始遍历的下标,也就是记录temp指到第几个了
		while(temp->next!=NULL)
		{
			if(s_index==index)
				break;
			else
			{
				++s_index;
				temp = temp->next;
			}
		}
		/*
		注意这里,如果要删除的数据是最后一个的话,就不能用下面那种:
		temp->next->next,这里会造成指针越界,因为next->next已经是NULL了
		*/
		if(s_index==length)
		{
			temp->next==NULL;
			delete temp;
		}
		else//不是最后一个数据执行这里
		{
			Node *nextNextNode = temp->next->next;
		/*
		防止指针释放不干净,所以要将指针的地址指向NULL(只是地址,不影响内容)
		比如你要添加一个新的节点放末尾
		结果计算机又分配到了这个被释放的指针
		而这时候又没有初始化,则这个指针可能还指着某个节点
		*/
			temp->next->next = NULL;
			delete temp->next;
			temp->next = nextNextNode;
			--length;
		}
	}
}

//找对象,这里下面两个都用到了相同功能的代码,方便!
Node* NodeManager::findNode(const char *_name)
{
	Node *temp = headNode.next;
	while(temp!=NULL)
	{
		if(strcmp(temp->data.name, _name)==0)
			return temp;
		else
			temp = temp->next;
	}
	//temp==NULL
	std::cout << "This guy's not on the list!\n";
	return temp;
}

void NodeManager::insertNode(const char *_name, Node *newNode)
{//这个有图解
	Node *temp = findNode(_name);
	if(temp==NULL)
		return ;
	else
	{
		newNode->next = temp->next;
		temp->next = newNode;
		++length;
	}
}

void NodeManager::updateNode(const char *oldName, char *newName, double acc)
{//其实这里的参数,可以跟上面的一样,主要看后面Menu.cpp咋写,就是交互问题,这里分两种方法展示了
	Node *temp = findNode(oldName);
	if(temp==NULL)
		return;
	else
	{
		strcpy(temp->data.name, newName);
		temp->data.account = acc;
	}
}

void NodeManager::showNode() const
{
	if(length==0)
	{
		std::cout << "Empty!\n";
		return;
	}
	using std::cout;
	Node *temp = headNode.next;
	for(int i=0; i<length; i++)
	{
		cout << "第" << i+1 << "个数据:\n"
		<< " Name: " << temp->data.name
		<< "\tAccount: " << temp->data.account << '\n';
		temp = temp->next;
	}
}

3.Menu.cpp

//这一整个cpp文件就是因为我嫌挤在一起丑弄的
#include<iostream>
#include"list.h"
using std::cout;
using std::cin;

void Add(NodeManager* manager)
{
	Node *temp = new Node;
	temp->next = NULL;
	cout << "请输入用户的姓名和账户密码:\n";
	cin.get();
	cin.getline(temp->data.name, size);
	cin >> temp->data.account;
	manager->addNode(temp);
	cout << "Add successfully!\n";
}

void Remove(NodeManager* manager)
{
	char _name[size];
	cout << "请输入要删除的用户的姓名:";
	cin.get();
	cin.getline(_name, size);
	manager->removeNode(_name);
	cout << "Remove successfully!\n";
}

void Update(NodeManager* manager)
{
	char _name[size], nName[size];
	int acc;
	cin.get();
	cout << "请输入要修改的用户的姓名:";
	cin.getline(_name, size);
	cout << "请输入新的用户名和密码:\n";
	cin.getline(nName, size);
	cin >> acc;
	manager->updateNode(_name, nName, acc);
	cout << "Update successfully!\n" ;
}

4.main.cpp

#include<iostream>
#include"list.h"

int main()
{
	using namespace std;

	NodeManager* manager = new NodeManager;
	bool isExit = true;
	int input;
	char _name[size];

	while(isExit)
	{
		cout << "\t1.添加数据" << endl
		<< "\t2.删除数据" << endl
		<< "\t3.修改数据" << endl
		<< "\t4.查看数据" << endl
		<< "\t5.退出" << endl
		<<"--------------------------------------" << endl;
		while(!(cin>>input))
		{
			cin.clear();
			while(cin.get() != '\n')
				continue;
			cout << "请重新输入!\n" ;
		}
		system("cls");
		switch(input)
		{
			case 1:
				Add(manager);
				break;
			case 2:
				Remove(manager);
				break;
			case 3:
				Update(manager);
				break;
			case 4:
				manager->showNode();
				break;
			case 5:
				isExit = false;
				break;
			default:
				cout << "请重新输入!" << endl;
		}
	}
}

有什么问题欢迎来提问鸭~
也欢迎各位大佬们前来指正!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值