数据结构-c++版-硬钢单链表

在这里插入图片描述

头节点->第一个节点->第二个节点->第三个节点->…->第n个节点(尾节点)->NULL

//单链表
#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
 
typedef struct _LinkNode {
	int date;//结点的数据域
	struct _LinkNode* next;//结点的指针域
}LinkNode,LinkList;//链表结点,链表

bool InitList(LinkList* &L) {//构造一个空的单链表
	//L是一个LinkList*类型的引用
	L = new LinkNode;//生成新结点作为头结点,用头指针L指向头结点
	if (!L)return false;//生成结点失败
	L->next = NULL;//头结点的指针域置空
	L->date = -1;//头结点没有值,这里可以赋值成-1
	return true;
}

前插法  =>依次把元素插在前面
//bool ListInsert_front(LinkList* &L, LinkNode* node) {
//	if (!L || !node)return false;
//	node->next = L->next;//左边是橄榄枝,右边人才本身
//	L->next = node;//左边是橄榄枝,右边人才本身
//	return true;
//}
 
//尾插法  =>依次把元素插在后面(只要找到最后一个元素即可)
bool ListInsert_back(LinkList* &L, LinkNode* node) {
	LinkNode* last = NULL;
	if (!L || !node)return false;

	last = L;
	while (last->next) last = last->next;//依次遍历找到最后一个节点(最后一个节点的特点:
	//最后一个节点的next为空)

	node->next = NULL;//左边是橄榄枝,右边人是受邀人
	last->next = node;//左边是橄榄枝,右边是受邀人
	return true;
}

//单链表的输出
void LinkPrint(LinkList* &L) {
	cout << "链表输出:" << endl;
	LinkList* p = NULL;//用一个临时指针来遍历
	if (!L) {
		cout << "链表为空." << endl;
		return;
	}
	p = L->next;
	while (p) {
		cout << p->date << "\t";
		p = p->next;
	}
	cout << endl;
	//delete p;   => 没有new怎么能用delete呢?
}

//在任意位置的插入
//指定位置插入
//也叫前插法
bool LinkInsert(LinkList* &L,int i,int &e) {//在位置i插入元素e
	if (!L) return false;

	int j = 0;
	LinkList* p, * s;
	p = L;

	//找到位置为i-1的节点,p指向该节点
	while (p && j < i - 1) {//当p不为空且j<i-1
		p = p->next;
		j++;
	}
	//要在节点2插入一个元素,就要找到节点1(节点和位置在数值上保持一致)
	// eg:在节点2插入一个元素
	//第一轮循环:0<2-1  =>p从头节点指向第一个节点
	//第二轮循环:1<1     =>不成立,循环结束

	if (!p||j>i-1) {
		//!p       防止出现你只有3个节点,但是你想在第5个节点插入的现象
		//j>i-1   防止你想在负位置插入(防止i=0和i<0的情况)(因为节点最小是1)
		return false;
	}

	//如果能走到这,说明已经    找到了   要插入位置  的  前一个节点   了
	s = new LinkNode;//生成新节点
	s->date = e;
	s->next = p->next;
	p->next = s;
	return true;

	//malloc一次free一次,new一次delete一次
	//函数调用完毕之后,堆空间是不会自动消失的!
	//函数调用完毕之后,指针变量s(存放在栈空间)没了,但是,之前申请的堆空间还在
	//=>也就是说,函数调用完毕之后,没有任何人指向之前申请的堆空间了,但是,内存,还在!
	delete s;
}

//单链表的取值
// 也叫按位查找
//按位置获取对应位置的元素
bool Link_GetElem(LinkList*& L, int i, int& e) {
	//在链表中查找第i个元素
	//用e记录链表第i个数据元素的值
	int index;
	LinkList* p;//临时的指针

	if (!L || !L->next) return false;
	//链表为空,或者只有一个头结点,直接return false

	p = L->next;
	index = 1;

	while (p&&index<i) {
		//p不为空,当index==i时,就找到了
		p = p->next;
		index++;  //计数器相应+1
	}

	if (!p || index > i) return false;//i值不合法,i>n或者i<=0

	e = p->date;
	return true;
}

//按值查找
bool Link_FindElem(LinkList *L,int e,int &index) {
	//在带头结点的单链表L中查找值为e的元素
	//并返回元素e的位置index

	LinkList* p;//临时的指针
	p = L->next;//让p指向第一个节点
	index = 1;

	if (!L || !L->next) { 
//链表为空,或者只有一个头结点,直接return false
		index = 0;//位置无效
		return false; 
	}
	
	while (p && p->date != e) {
		//p不为空,当p->date == e时,就找到了
		p = p->next;
		index++;
	}

	if (!p) {
//查无此值
		index = 0;//位置无效
	return	false;
	}

	return true;
}

//单链表删除元素
bool LinkDelete(LinkList*& L, int i) {
	//删除节点i
//要删除第二个节点,就要找到第一个节点
	LinkList* p, * q;

	int index = 0;
	p = L;//从头结点开始

	if (!L || !L->next) {
		return false;
	}

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

	if (!p->next || index > i - 1) {//当i>n或i<1时,删除位置不合理
		return false;
	}

	q = p->next;//这里q并没有抛出橄榄枝,然而直接把q变成了p->next本身
	p->next = q->next;//左边是橄榄枝,右边是受邀人(只有左边是->next时,才是抛出橄榄枝)

	delete q;//释放删除节点q的内存
	return true;
}

//销毁单链表
void LinkDextory(LinkList* &L) {
	//定义临时节点p指向头结点
	LinkList* p = L;
	cout << "正在销毁单链表..." << endl;
	while (p) {
		L = L->next;//L指向下一个节点
		cout << "删除元素:" << p->date << endl;
		delete p;//删除当前节点
		p = L;//p移向下一个节点
	}
	cout << "销毁单链表成功!" << endl;
}

int main() {
	LinkList* L = NULL;//L作为主体链表
	LinkList* s = NULL;//s作为要插入的新链表

	//初始化一个空的链表
	InitList(L);
	cout << "初始化链表成功" << endl;

	//使用前插法插入数据
	//int n;
	//cout << "前插法创建单链表" << endl;
	//cout << "请输入n个元素:";
	//cin >> n;
	//cout << "\n请依次输入n个元素" << endl;
	//while (n > 0) {
	//	s = new LinkNode;//生成新结点s   //新结点指针域
	//	cin >> s->date;   //新结点数据域
	//	ListInsert_front(L, s);
	//	n--;
	//}


	//使用尾插法插入数据
	int n;
	cout << "尾插法创建单链表!" << endl;
	cout << "请输入您要创建元素的个数:";
	cin >> n;
	cout << "\n请依次输入" << n << "个元素" << endl;
	while (n > 0) {
		s = new LinkNode;//生成新结点s   //新结点指针域
		cin >> s->date;   //新结点数据域
		ListInsert_back(L, s);
		n--;
	}

	//单链表的输出
	LinkPrint(L);

	//任意位置插入
	printf("这里插入3次.\n");
	for (int j = 0; j < 3; j++) {
		int i, x;
		cout << "请输入要插入的位置和元素(用空格隔开):" << endl;
		cin >> i >> x;

		if (LinkInsert(L, i, x)) {
			cout << "插入成功\n";
		}
		else {
			cout << "插入失败哦\n";
		}
		LinkPrint(L);
	}

	int element = 0;
	if (Link_GetElem(L, 2, element)) {
		cout << "获取第二个元素成功!  值: " << element << endl;
	}
	else {
		cout << "获取第二个元素失败哦!" << endl;
	}

	int index = 0;
	if (Link_FindElem(L, 10, index)) {//查找元素10的位置
		cout << "查找元素10的位置是:" << index << endl;
	}
	else {
		cout << "查无此值" << endl;
	}

	if (LinkDelete(L, 2)) {
		cout << "删除第2个元素成功!" << endl;
		LinkPrint(L);
	}
	else {
		cout << "删除第2个元素失败" << endl;
		LinkPrint(L);
	}

	LinkDextory(L);

	system("pause");
	return 0;
}


在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踏过山河,踏过海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值