C++单链表,增,改,删,查

27 篇文章 1 订阅

单链表的各种操作

运行环境:VS2022
运行位数:X64

注释齐全
在这里插入图片描述

#include <iostream>
#include <Windows.h>
#include <string>

using namespace std;
typedef struct _LinkNode {
	int data;					//结构点的数据域
	struct _LinkNode* next;		//节点的指针域
}LinkNode, Linklist;			//Linklist是头结点 LinkNode是增加的节点

//初始化
bool InitList(Linklist*& L) {	//构造一个空的单链表
	L = new LinkNode;			//生成新结点作为头结点,用头指针 L 指向头结点
	if (!L) { return false; }	//失败
	L->next = NULL;				//头结点的指针域置空
	return true;
}

bool ListInstrt_front(Linklist*& L, LinkNode* node) {	//	前插法
	if (!L || !node) { return false; }

	node->next = L->next;	//存下一个节点的地址
	L->next = node;			//把自己的地址赋值到上一个节点的指针域
	/*
	* 插入一个新元素,是先让自己的指针域指向下一个节点
	* 然后在让上一个节点的指针域指向自己
	*/

	return true;
}

bool ListInstrt_back(Linklist*& L, LinkNode* node) {	//尾插法
	if (!L || !node) { return false; }
	LinkNode* p = NULL;
	/*
	* 之所以要定义一个指针不使用原本的L是因为L是头结点
	* 头结点不能移动,所以要定义一个指针移动到最后一个节点
	*/
	p = L;
	while (p->next)p = p->next;
	/*
	* p->next是判断p->next是否为真
	* 为真就执行p = p->next,
	*因为p->next里面存的值就是下一个节点的值,把下一个节点的值赋值到p
	*就进入到下一个节点了.从而一直遍历到尾结点
	*/

	node->next = NULL;		//存的下一个节点的地址
	p->next = node;			//将上一个节点的指针域指向自己
	return true;
}

bool LinkInsert(Linklist*& L, int i, int& e) {	//在任意位置插入节点
	int j = NULL;
	Linklist* p, * s;

	p = L;
	while (p && j < i - 1) {
		p = p->next;
		j++;
	}
	if (!p || j > i - 1) {
		cout << "插入失败!" << endl;
		return false;
	}

	s = new LinkNode;
	s->data = e;
	s->next = p->next;	//将新插入的节点的指针域指向下一个节点
	p->next = s;		//将上一个节点的指针域指向自己

	return true;

}


void Linkprint(Linklist*& L) {
	Linklist* p = NULL;
	if (!L) { cout << "链表中没有数据!"; return; }

	p = L->next;
	while (p) {
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}

bool Link_GetElem(Linklist*& L, int i, int& e) {//单链表的取值
	int j = NULL;
	Linklist* p = NULL;

	p = L->next;	//将第一个节点赋值到p
	j = 1;

	while (j < i && p) {
		p = p->next;
		j++;
	}

	if (!p || j > i) { return false; }
	e = p->data;
	return true;

}

bool Link_FindElem(Linklist* L, int e) {//按值查找
	Linklist* p = NULL;

	p = L->next;

	while (p && p->data != e) {
		p = p->next;
	}

	if (!p) { return false; }

	return true;
}

bool LinkDelete(Linklist*& L, int i) {	//单链表的删除
	Linklist* p = NULL, * q = NULL;
	int j = NULL;
	p = L;
	/*
	*减一是因为要删除节点,只需要删除被删除节点的前一个节点的指针域
	*因为被删除节点的前一个节点的指针域存储的就是下一个节点的地址
	*只需要把被删除节点的前一个节点的指针域重新链接到不需要删除的节点就可以了
	*/
	while ((p->next) && (j < i - 1)) {
		p = p->next;
		j++;
	}

	if (!(p->next) || (j > i - 1)) { return false; }
	/*
	* q = p->next;解析
	*p是被删除节点的前一个节点,p->next就是当前要删除的节点
	*把当前要删除的节点暂时赋值给q;
	*/
	q = p->next;	//临时保存被删结点的地址以备释放空间

	/*
	* p->next = q->next;解析
	*q现在是被删除的节点,q->next是被删除节点的下一个节点
	*把被删除节点的下一个节点,赋值给被删除的前一个节点
	*/
	p->next = q->next;	//改变删除结点前驱结点的指针域

	delete q;			//释放被删除结点的空间
	return true;
}

void LinkDestroy(Linklist*& L) {//单链表的销毁
	Linklist* p = L;

	cout << "销毁链表!!" << endl;
	while (p) {
		L = L->next;	//把第一个节点的地址赋值到L
		cout << "删除节点!!" << p->data << endl;
		delete p;		//释放节点
		p = L;			//把第一个节L点赋值给P
	}
}

bool ListAmend(Linklist*& L, int i, int j) {//i 节点的位置, j 修改的数据
	Linklist* p = NULL;
	int a = NULL;
	p = L;

	//遍历节点
	while (p && a < i) {
		p = p->next;
		a++;
	}

	if (!p || a > i) { return false; }

	p->data = j;
	return true;
}
void ListInstrt_back1(Linklist*& L) {
	int e = NULL;
	Linklist* s2 = NULL;

	cout << "请输入需要插入的个数(尾插法):";
	cin >> e;
	while (e > 0) {
		s2 = new LinkNode;

		cout << "请输入数据:";
		cin >> s2->data;
		if (ListInstrt_back(L, s2)) {
			cout << "插入成功!!" << endl;
			e--;
		}
		else {
			cout << "插入失败!!" << endl;
			return;
		}

	}
	Linkprint(L);
}

void ListInstrt_front1(Linklist*& L) {
	Linklist* s2 = NULL;
	int e = NULL;

	cout << "请输入需要插入的个数(前插法):";
	cin >> e;
	while (e > 0) {
		s2 = new LinkNode;

		cout << "请输入数据:";
		cin >> s2->data;
		if (ListInstrt_front(L, s2)) {
			cout << "插入成功!!" << endl;
			e--;
		}
		else {
			cout << "插入失败!!" << endl;
			return;
		}


	}
	Linkprint(L);
}

void LinkInsert1(Linklist*& L) {
	int e = NULL;
	int b = NULL;

	cout << "请输入插入的个数:";
	cin >> b;
	while (b > 0) {
		int a = NULL;
		e = NULL;

		cout << "当前数据:";
		Linkprint(L);

		cout << "请输插入的位置和数据(空格隔开):";
		cin >> a >> e;

		if (LinkInsert(L, a, e)) {
			cout << "插入成功!!" << endl;
			Linkprint(L);
			b--;
		}
		else {
			cout << "插入失败!!" << endl;
			return;
		}


	}

}

void Link_GetElem1(Linklist*& L) {
	int i = NULL;
	int e1 = NULL;
	while (true) {
		cout << "请输入需要查询的节点(按0退出):";
		cin >> i;
		if (i == 0) { break; }
		if (Link_GetElem(L, i, e1)) {
			cout << "节点的数据域值是:" << e1 << endl;
		}
		else {
			cout << "该值不存在" << endl;
		}
	}
}

void Link_FindElem1(Linklist*& L) {
	while (true) {
		int i = NULL;
		cout << "请输入需要查询的值(输入0结束):";
		cin >> i;
		if (i == 0) { break; }

		if (Link_FindElem(L, i)) {
			cout << "查找的:" << i << "存在!" << endl;
		}
		else {
			cout << "查找的:" << i << "不存在!" << endl;
		}
	}
}

void ListAmend(Linklist*& L) {
	while (true) {
		int x = NULL;
		int y = NULL;
		cout << "请输入需要修改数据的节点,以及修改的数据(空格隔开,按0结束):";
		cin >> x >> y;
		if (x == 0) { break; }
		if (ListAmend(L, x, y)) {
			cout << "修改成功!!" << endl;
			Linkprint(L);
		}
		else {
			cout << "修改失败!!" << endl;
			return;
		}
	}
}

void LinkDelete1(Linklist*& L) {
	while (true) {
		int a = NULL;

		cout << "请输入需要删除的节点(按0结束):";
		cin >> a;
		if (a == 0) { break; }

		if (LinkDelete(L, a)) {
			cout << "删除成功!!" << endl;
			Linkprint(L);
		}
		else {
			cout << "删除失败!!" << endl;
		}
	}
}
void function() {
	Linklist* s1;	//头结点
	InitList(s1);	//初始化一个空的单链表,也就是初始化头节点

	while (true) {
		int x = NULL;
		string str[]{
					"      单链表         \n"
					"1.插入数据(尾插法)   \n"
					"2.插入数据(前插法)   \n"
					"3.任意位置插入数据   \n"
					"4.按节点查询数据     \n"
					"5.查询数据是否存在   \n"
					"6.修改任意节点的数据 \n"
					"7.查看链表中的数据	  \n"
					"8.删除任意节点       \n"
					"9.销毁链表           \n"
					"10.退出               \n"
		};
		cout << *str << endl;
		cout << "请输入需要执行的操作:";
		cin >> x;

		if (x <= 0 || x > 11) { cout << "条件不成立!!" << endl; return; }

		switch (x) {
		case 1:
			ListInstrt_back1(s1);
			system("pause");
			break;
		case 2:
			ListInstrt_front1(s1);
			system("pause");
			break;
		case 3:
			LinkInsert1(s1);
			system("pause");
			break;
		case 4:
			Link_GetElem1(s1);
			system("pause");
			break;
		case 5:
			Link_FindElem1(s1);
			system("pause");
			break;
		case 6:
			ListAmend(s1);
			system("pause");
			break;
		case 7:
			cout << "链表中的所有数据:";
			Linkprint(s1);
			system("pause");
			break;
		case 8:
			LinkDelete1(s1);
			system("pause");
			break;
		case 9:
			cout << "销毁链表后,就无法进行任何对链表的操作!!" << endl;
			LinkDestroy(s1);
			system("pause");
			break;
		case 10:
			exit(0);
			break;
		default:
			break;
		}


		system("cls");
	}
}

int main(void) {

	function();

	system("pause");
	return 0;
}
链表原理

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的C++单链表的例子,用于管理火车信息: ```c++ #include <iostream> #include <string> using namespace std; // 火车信息结构体 struct Train { string name; // 火车名 string departure; // 出发地 string destination; // 目的地 int time; // 发车时间 }; // 单链表节点结构体 struct Node { Train data; // 数据域 Node* next; // 指针域 }; // 单链表类 class LinkedList { public: LinkedList() { head = new Node(); // 创建头节点 head->next = nullptr; } // 添加节点 void addNode(Train train) { Node* newNode = new Node(); newNode->data = train; newNode->next = nullptr; Node* p = head; while (p->next != nullptr) { p = p->next; } p->next = newNode; } // 节点 bool deleteNode(string name) { Node* p = head->next; Node* pre = head; while (p != nullptr) { if (p->data.name == name) { pre->next = p->next; delete p; return true; } pre = p; p = p->next; } return false; } // 修改节点 bool modifyNode(string name, Train train) { Node* p = head->next; while (p != nullptr) { if (p->data.name == name) { p->data = train; return true; } p = p->next; } return false; } // 节点 Train* findNode(string name) { Node* p = head->next; while (p != nullptr) { if (p->data.name == name) { return &p->data; } p = p->next; } return nullptr; } // 输出所有节点 void printAll() { Node* p = head->next; while (p != nullptr) { cout << "火车名:" << p->data.name << endl; cout << "出发地:" << p->data.departure << endl; cout << "目的地:" << p->data.destination << endl; cout << "发车时间:" << p->data.time << endl << endl; p = p->next; } } private: Node* head; }; // 主函数 int main() { LinkedList list; // 添加节点 Train train1 = { "G101", "北京", "上海", 800 }; Train train2 = { "D312", "上海", "广州", 1100 }; Train train3 = { "Z54", "北京", "武汉", 1300 }; list.addNode(train1); list.addNode(train2); list.addNode(train3); // 输出所有节点 cout << "所有火车信息:" << endl; list.printAll(); // 节点 cout << "除火车信息:" << endl; list.deleteNode("D312"); list.printAll(); // 修改节点 cout << "修改火车信息:" << endl; Train train4 = { "Z54", "北京", "长沙", 1300 }; list.modifyNode("Z54", train4); list.printAll(); // 节点 cout << "找火车信息:" << endl; Train* train5 = list.findNode("G101"); if (train5 != nullptr) { cout << "火车名:" << train5->name << endl; cout << "出发地:" << train5->departure << endl; cout << "目的地:" << train5->destination << endl; cout << "发车时间:" << train5->time << endl; } else { cout << "没有找到该火车信息" << endl; } return 0; } ``` 这段代码实现了单链表操作,你可以根据需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值