数据结构——单链表实现

 看完B站《王道考研》单链表有关的函数,自己实现了一遍,没有书,纯自己手动敲,有些函数声明定义不是很规范(主要是写给自己看的^_^)

实现了6个函数:

void PrintLink(ld Head);//打印链表
ld HeadChaFa(ld Head);//头插法创建链表(自己写的时候不会英文,用拼音吧 ̄▽ ̄)
ld WeiChaFa(ld Head);//尾插法创建链表
bool ChaRu1(ld Head, int i, int x);//按序位插入
bool InsertNextNode(ld Head, int x);//按给定结点数字后插(偷偷看了一下视频里的函数名)
bool InsertPriorNode(ld Head, int x);//按给定结点数字前插

/*
	单链表的实现
*/
typedef struct LNode* ld;
struct LNode {
	int data;
	ld next;
};
typedef enum { false,true }bool;
void PrintLink(ld Head);
ld HeadChaFa(ld Head);
ld WeiChaFa(ld Head);
bool ChaRu1(ld Head, int i, int x);
bool InsertNextNode(ld Head, int x);
bool InsertPriorNode(ld Head, int x);
int main() {
	ld LHead=NULL;		//创建一个头结点LHead
	printf("开始创建链表(输入范围为整型,输入-9999退出创建):");
	/*
		接下来利用头插法创建链表:
		LHead = HeadChaFa(LHead);
		打印链表
		PrintLink(LHead);*/

	//接下来利用尾插法创建链表:
	LHead = WeiChaFa(LHead);

	//接下来实现链表的插入:
	/*	1.按输入序号插入
	int i,x;
	printf("请输入你要插入的第i个位置(输入大于等于1):");
	scanf("%d", &i);
	printf("你要插入的元素x是:");
	scanf("%d", &x);
	if (!ChaRu1(LHead, i, x)) {
		printf("输入位置有误\n");
	}
	*/
	/*	2.插在给定结点的值的后方 与B站《王道计算机考研》数据结构给定节点不同,我按给定结点里面的数字来,区别在于要从头遍历,下面的“插在给定结点数据的前方”也是同理
	int x;
	printf("请输入给定结点的data是:");
	scanf("%d", &x);
	if (!InsertNextNode(LHead, x)) {
		printf("数据不存在链表中或者链表为空");
	}
	*/
	/*	3.插在给定结点的值的前方
	*/
	int x;
	printf("请输入给定结点的data是:");
	scanf("%d", &x);
	if (!InsertPriorNode(LHead, x)) {
		printf("数据不存在链表中或者链表为空");
	}
	//打印链表
	PrintLink(LHead);
	return 0;
}
ld HeadChaFa(ld Head) {//头插法创建链表
	Head = (ld)malloc(sizeof(struct LNode));//创建一个头结点,并指向空
	Head->next = NULL;//这一步很关键,因为是用头插法,所以最后一个元素指向的是初始时头结点的next指向的地址
					//如果没有指向NULL,那么最后一个元素会指向一篇未知的区域
	ld p;//创建一个p指针,指向新创建的结点
	int x;
	scanf("%d", &x);//输入x判断插入操作
	while (x != -9999) {//等于-9999时退出操作
		//开始头插操作
		p = (ld)malloc(sizeof(struct LNode));
		p->data = x;
		p->next = Head->next;
		Head->next = p;
		scanf("%d", &x);//改变循环变量,不然死循环了,疯狂申请内存很可怕的

	}
	return Head;
}
ld WeiChaFa(ld Head) {//尾插法创建链表
	Head = (ld)malloc(sizeof(struct LNode));
	Head->next = NULL;
	ld p, q;
	p = q = NULL;
	p = Head;
	int x;
	scanf("%d", &x);
	while (x != -9999) {
		q = (ld)malloc(sizeof(struct LNode));
		q->data = x;
		//q->next =NULL;  可以放在循环结束之后
		p->next = q;
		p = q;
		scanf("%d", &x);
	}
	p->next = NULL;
	return Head;
}
bool ChaRu1(ld Head, int i, int x) {//按位序的插入法
	if (i < 1)
		return false;
	int j = 0;//记录到达i处时刻的数字指针
	ld p=NULL;//链表前驱
	p = Head;
	//先把前驱移动到要插入到的位置的前一个
	while (p->next != NULL&&j++<i-1) {
		p = p->next;
	}
	if (p == NULL)   //如果输入的i太大,则无法插入
		return false;
	ld s = (ld)malloc(sizeof(struct LNode));
	s->data = x;
	s->next = p->next;
	p->next = s;
	printf("插入成功 ");
	return true;
}
bool InsertNextNode(ld Head, int x) {//按指定结点数据的后插操作

	ld p = NULL;
	p = Head;
	int i=0;//指定结点在第几个位置上
	while (p->next != NULL && p->data != x) {
		p = p->next;
		i++;
	}
	if (p == NULL)			//说明链表中不存在指定的数字
		return false;
	int s;
	printf("找到x了,它在第%d个位置上,现在你要插入的数据s是:", i);
	scanf("%d", &s);
	ld q = (ld)malloc(sizeof(struct LNode));
	q->data = s;
	q->next = p->next;
	p->next = q;
	printf("插入成功 ");
	return true;
}
bool InsertPriorNode(ld Head, int x) {//按指定结点数据的前插操作

	ld p = NULL;
	p = Head;
	int i = 0;//指定结点在第几个位置上
	while (p->next != NULL && p->data != x) {
		p = p->next;
		i++;
	}
	if (p == NULL)			//说明链表中不存在指定的数字
		return false;
	int s;
	printf("找到x了,它在第%d个位置上,现在你要插入的数据s是:", i);
	//前面和插入指定结点后一样,要插在前面可以用用复制的思想:
	//将新结点的数据与p所在的结点的数据互换位置即可,这也相当于在给定结点前插入一个新结点
	ld q = (ld)malloc(sizeof(struct LNode));
	q->data = p->data;//先将p结点的data赋值给新结点的data
	scanf("%d", &s);//再输入新的data
	p->data = s;
	//同样的将新结点链接在p后面,这里的“前插”只是名义上的,底层实现还是“后插” 因为不是双向指针,找不到他的前一个指针的地址了,所以用互换data的方法实现类似的效果
	q->next = p->next;
	p->next = q;
	printf("插入成功 ");
	return true;
}
void PrintLink(ld Head) {
	ld p;//用p前驱去移动打印链表,而不直接用传来的Head,因为传来的Head会改变外面的头结点指针
	p = Head;
	printf("链表元素分别是:");
	while (p -> next != NULL) {
		p = p->next;//一定不要忘了移动指针
		printf("%d ", p->data);
		
	}
}

 bool InsertPriorNode函数,有个很妙的解法,当p前驱找到输入数据对应结点后,想要前插,其实并不需要真正的前插,和后插一样的操作,加上一点点骚操作:把新插入结点中的data与p结点的data交换一下位置即可实现表观意义上的“前插”(借用王道数据结构的图理解一下)

 

 思路还是很新颖的

bool InsertPriorNode(ld Head, int x) {//按指定结点数据的前插操作

	ld p = NULL;
	p = Head;
	int i = 0;//指定结点在第几个位置上
	while (p->next != NULL && p->data != x) {
		p = p->next;
		i++;
	}
	if (p == NULL)			//说明链表中不存在指定的数字
		return false;
	int s;
	printf("找到x了,它在第%d个位置上,现在你要插入的数据s是:", i);
	//前面和插入指定结点后一样,要插在前面可以用用复制的思想:
	//将新结点的数据与p所在的结点的数据互换位置即可,这也相当于在给定结点前插入一个新结点
	ld q = (ld)malloc(sizeof(struct LNode));
	q->data = p->data;//先将p结点的data赋值给新结点的data
	scanf("%d", &s);//再输入新的data
	p->data = s;
	//同样的将新结点链接在p后面,这里的“前插”只是名义上的,底层实现还是“后插” 因为不是双向指针,找不到他的前一个指针的地址了,所以用互换data的方法实现类似的效果
	q->next = p->next;
	p->next = q;
	printf("插入成功 ");
	return true;
}

还有,我用的是C语言环境下实现,C语言里没有直接的bool类型,要么调包(但是忘了是哪个包的话就......)还有一种就是利用枚举常量enum(刚好可以复习一下enum)

typedef enum { false,true }bool;

 还有删除和查找没实现,改天再说吧

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值