C语言的链表【2019.9.22】

前言吐槽

今日学习内容是C语言的单链表,本人真的是被C逼疯了,此话怎讲呢?本人学校内开的课程里有C语言,但是······我感觉我对C的感觉就跟看汇编一样,没兴趣···倒不是看不懂程序,毕竟我还会点C#,但糟心就糟心在在学习C的时候,我遇见了一个“神奇”的老师,她有个爱好叫做——“照着书打字呀,好好看着书打呀。”
比如你写程序书上是%d,你就必须是%d,不然她就说你不会打字,啧,我又不是学打字的【摊手】

编写C语言的链表

C的难度蛮大的,很多东西我们需要自己去申明,像我昨天写的Java程序那叫一个舒爽,别的都不管,做个链表也不用自己去做一个数据域,但是C语言需要
这里做一个小笔记
C语言是个很自由的编程语言,所以很多知识不知道的话,是没有思路写下去的,因为它过分自由了,导致编写它有相当严格的知识储备要求,如果做不到这些储备的,就和我一样找个c语言代码看着,如果有其他语言的底子,看懂大概意思是不成问题的。
所以我一直秉持一个态度:程序没思路,先去看看别人的思路,不会就照着打直到打字打懂
上程序了

PNode CreateList(void) 
{
	int len;    //    用于定义链表的长
	int val;    //    用于存放节点数值
	PNode PHead = (PNode)malloc(sizeof(Node));    //    创建分配一个头节点内存空间
	if (PHead == NULL)    //    判断是否分配成功
	{
		printf("空间分配失败 \n");
		exit(-1);
	}

	PNode PTail = PHead;    //    链表的末尾节点,初始指向头节点
	PTail->Next = NULL;    //    最后一个节点指针置为空
	printf("请输入节点个数:");
	scanf_s("%d", &len);        //    输入节点个数
	for (int i = 0; i < len; i++) 
	{
		PNode PNew = (PNode)malloc(sizeof(Node));    //    分配一个新节点
		if (PNew == NULL) 
		{
			printf("分配新节点失败\n");
			exit(-1);
		}
		printf("请输入第 %d 个节点的数据:", i + 1);
		scanf_s("%d", &val);    //    输入链表节点的数据

		PNew->Element = val;    //    把数据赋值给节点数据域
		PTail->Next = PNew;    //    末尾节点指针指向下一个新节点
		PNew->Next = NULL;        //    新节点指针指向为空
		PTail = PNew;    //    将新节点复制给末尾节点        
	}
	printf("创建链表成功\n");
	return PHead;    //    返回头节点
}

对比Java的创建

我感觉真的差的不是一丁半点啊,各位可以对比一下看看

public class Mylink {
	Node head = null; // 使用給定值初始化新節點node
	public static final int Subscript= 1;
	class Node {
		Node next = null;// 將cur的next的字段链接到下一个结点
		int val;//定义一个值,作为节点内容

		public Node(int data) {
			this.val = data;
		}
	}

删除数据

跟大家上程序来感受一下,Java、和c语言的魅力
先是Java

public boolean deleteNode(int index) {
		if (index < 1 || index > length()) {
			System.out.println("删除错误");
			return false;
		}
		if (index == 1) {
			head = head.next;
			System.out.println("删除成功!");
			return true;
		}
		int i = 1;
		Node preNode = head;
		Node curNode = preNode.next;
		while (curNode != null) {
			if (i == index) {
				preNode.next = curNode.next;
				return true;
			}
			preNode = curNode;
			curNode = curNode.next;
			i++;
		}
		return false;
	}

再来c语言

void DeleteList(PNode List, int pos) {
	int position = 0;
	PNode P = List;    //    定义一个指针p指向链表头节点
					//    寻找pos节点位置的前驱节点
	while (P != NULL && position < pos - 1) {
		P = P->Next;
		++position;
	}

	//    删除节点
	PNode Tmp = P->Next;    //    定义临时指针Tmp指向要删除的节点
	P->Next = Tmp->Next;    //    使要删除节点的前驱结点指向其后驱节点
	free(Tmp);    //    释放删除节点的内存空间,防止内存泄漏
	Tmp = NULL;    //    使q指向空指针,防止产生野指针
}

看到现在,我脑阔疼,为什么会有c语言这么自由自在的语言呢?很多在Java,C#,python中可以直接用的东西,但在C里你就学会踏踏实实的做人,专门克制那些花里胡哨的骚操作···
接下来就不废话了,直接看程序吧,这个注释应该是可以看的,看不看得懂看大家的造化了

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

typedef int ElementType;        //    定义数据类型,可根据需要进行其他类型定义
								//    链表节点的定义
typedef struct ListNode
{
	ElementType  Element;        //    数据域,存放数据
	ListNode* Next;        //    指向下一个链表节点
}
Node, * PNode;

//  ---------------   函数声明  ------------------
PNode CreateList(void);    //    声明创建链表函数
void TraverseList(PNode List);    //    声明遍历链表函数
void InsertlinkList(PNode List, int pos, int val);        //    声明链表插入函数
void DeleteTheList(PNode List);    //    声明删除整个链表函数
void DeleteList(PNode List, int pos);    //    声明删除链表元素函数
PNode FindList(PNode List);    //    声明链表查询函数

/*------------------   主函数   ---------------*/
int main() {
	PNode List = CreateList();    //    创建一个指针,使其指向新创建的链表的头指针    
	TraverseList(List
	);        //    遍历链表
	FindList(List);        //    链表查询    
	InsertlinkList(List, 3, 100);    //    链表插入,在第三个位置插入数值100
	TraverseList(List); 
	DeleteList(List, 3);    //    删除链表第三个节点
	TraverseList(List);
	DeleteTheList(List);    //    删除整个链表
	TraverseList(List);
	return 0;
}

/*--------------------------
 *NAME:CreateList
 *作用:创建链表函数定义
 *--------------------------
 */
PNode CreateList(void) 
{
	int len;    //    用于定义链表长度
	int val;    //    用于存放节点数值
	PNode PHead = (PNode)malloc(sizeof(Node));    //    创建分配一个头节点内存空间
	if (PHead == NULL)    //    判断是否分配成功
	{
		printf("空间分配失败 \n");
		exit(-1);
	}

	PNode PTail = PHead;    //    链表的末尾节点,初始指向头节点
	PTail->Next = NULL;    //    最后一个节点指针置为空
	printf("请输入节点个数:");
	scanf_s("%d", &len);        //    输入节点个数
	for (int i = 0; i < len; i++) 
	{
		PNode PNew = (PNode)malloc(sizeof(Node));    //    分配一个新节点
		if (PNew == NULL) 
		{
			printf("分配新节点失败\n");
			exit(-1);
		}
		printf("请输入第 %d 个节点的数据:", i + 1);
		scanf_s("%d", &val);    //    输入链表节点的数据

		PNew->Element = val;    //    把数据赋值给节点数据域
		PTail->Next = PNew;    //    末尾节点指针指向下一个新节点
		PNew->Next = NULL;        //    新节点指针指向为空
		PTail = PNew;    //    将新节点复制给末尾节点        
	}
	printf("创建链表成功\n");
	return PHead;    //    返回头节点
}

/*--------------------------
 *NAME:TraverseList
 *作用:定义链表遍历函数
 *参数:PNode List
 *--------------------------
 */
void TraverseList(PNode List)
{
	PNode P = List->Next;    //    首节点赋值给临时节点P
	printf("遍历链表的值为:");
	if (P == NULL)
		printf("链表为空");
	while (P != NULL)        //当临时节点P不为尾节点时,输出当前节点值 
	{
		printf("%d ", P->Element);
		P = P->Next;
	}
	printf("\n");
}

/*-------------------------
 *NAME:FindList
 *作用:定义链表查询函数
 *参数:PNode List
 *-------------------------
 */
PNode FindList(PNode List)
{
	PNode P = List->Next;    //    定义临时指针P指向首节点的地址
	int num = 0;    //    用于记录链表节点位置
	int val = 0;    //    用于存放要查询的值
	printf("请输入要查询的数:");
	scanf_s("%d", &val);    //    输入要查询的数值
	while (P != NULL && P->Element != val)
	{
		P = P->Next;
		++num;
	}
	if (P != NULL)
		printf("找到的节点为:%d", num + 1);
	else
		printf("找不到该节点");
	printf("\n");
	return P;
}
/*------------------------------------------------------
 *NAME:InsertList
 * 作用:定义链表插入函数
 * 操作:在链表位置第pos节点前插入包含数据val的节点
 * 参数:PNode List, int pos, int val
 *------------------------------------------------------
*/
void InsertlinkList(PNode List, int pos, int val) {
	int position = 0;
	PNode P = List;    //    定义节点p指向头节点
					//    寻找pos节点的前驱结点
	while (P != NULL && position < pos - 1)
	{
		P = P->Next;
		++position;
	}
	PNode Tmp = (PNode)malloc(sizeof(Node));    //    分配一个临时节点用来存储要插入的数据
	if (Tmp == NULL)
	{
		printf("内存分配失败!");
		exit(-1);
	}
	//    插入节点
	Tmp->Element = val;
	Tmp->Next = P->Next;
	P->Next = Tmp;
}

/*--------------------------------
 *NAME: DeleteTheList
 *作用:定义删除整个链表函数
 *参数:PNode List
 *--------------------------------
 */
void DeleteTheList(PNode List)
{
	PNode P, Tmp;
	P = List->Next;    //定义指针P指向链表要删除的链表List的第一个点节点
	List->Next = NULL;
	while (P != NULL) 
	{
		Tmp = P->Next;        //临时Tmp指向要删除的节点的下个节点
		free(P);    //释放指针P指向的节点
		P = Tmp;    //重新赋值
	}
	printf("删除链表成功!\n");
}
/*------------------------------------------------ 
 *NAME: DeleteList
 *作用:定义删除链表元素函数,删除链表中的第pos节点
 *参数:PNode List, int pos
 *------------------------------------------------
*/
void DeleteList(PNode List, int pos) {
	int position = 0;
	PNode P = List;    //    定义一个指针p指向链表头节点
					//    寻找pos节点位置的前驱节点
	while (P != NULL && position < pos - 1) {
		P = P->Next;
		++position;
	}

	//    删除节点
	PNode Tmp = P->Next;    //    定义临时指针Tmp指向要删除的节点
	P->Next = Tmp->Next;    //    使要删除节点的前驱结点指向其后驱节点
	free(Tmp);    //    释放删除节点的内存空间,防止内存泄漏
	Tmp = NULL;    //    使q指向空指针,防止产生野指针
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值