结构体终结篇,链表基本操作

结构体-完整的结构体笔记

什么是链表

链表就是一个结构体变量

struct people
{
	char name[20];
	int age;
	int num;
	char addr[20];
};

struct Node
{
	//int data;       //数据域
	struct MM data;   //指针域
	struct Node* next;
};

链表的一个结点包括数据域和指针域
在这里插入图片描述
用第一个节点表示整个链表
头节点:没有存数据 有头链表,常用
首节点:存数据 无头链表

静态内存申请

手动申请,手动释放

#include <stdio.h>
struct MM 
{
	char name[20];
	int age;
	int num;
};

struct Node 
{
	//struct MM data;
	int data;			//数据域
	struct Node* next;	//指针域
};

int main()
{
	struct Node node1 = { 1,NULL };
	struct Node node2 = { 2,NULL };
	struct Node node3 = { 3,NULL };
	node1.next = &node2;
	node2.next = &node3;
	struct Node* pMove = &node1;
	while(pMove!=NULL)
	{
		printf("%d\t", pMove->data);
		pMove = pMove->next;
	}
	//1.链表是什么?
	//2.链表怎么表示
	//3.链表如何打印

	return 0;
}

动态内存申请

#include <stdio.h>
#include <stdlib.h>
struct Node //节点结构体
{
	int data;
	struct Node* next;
};
1.没有在封装
用第一个节点表示整个链表
有头链表: 1.创建表头--->创建结构体变量
用指针表示结构体变量?
   1.1用变量地址初始化,
   1.2动态内存申请
//1.创建表头,即创建结构体变量
struct Node* createHead()
{
	//1.动态内存申请
	struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
	//(*headNode).next = NULL;
	headNode->next = NULL;//变量要初始化
	return headNode;   //返回变量
}

在这里插入图片描述
2.创建节点—>把用户数据加工成节点为插入准备

struct Node* createNode(int data) 
{   
	struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
	newNode->data = data;
	newNode->next = NULL;  //作为链表结束标志
	return newNode;
}

在这里插入图片描述

//3.表头插入
//自己写时候,参数要能够解释出意思
//以headNode 为表头链表
//插入的数据是data
void insertByHead(struct Node* headNode,int data)
{
	struct Node* newNode = createNode(data);	//调用自己写的函数
	//下面两句先后顺序不能交换
	//先连后断
	newNode->next = headNode->next;
	headNode->next = newNode;
	/*
		headNode->next = newNode;
		newNode->next = headNode->next;  //newNode->next = newNode
	*/
}

在这里插入图片描述

//4.表尾插入
void insertByTail(struct Node* headNode, int data) 
{
	struct Node* newNode = createNode(data);
	struct Node* pTail = headNode;
	while (pTail->next != NULL) 
	{
		pTail = pTail->next;
	}
	pTail->next = newNode;
}
//5.指定位置插入
//data:插入的数据
//posData: 指定位置
void insertByAppoin(struct Node* headNode, int data, int posData) 
{
	//做这种查找类插入,先不要着急创建节点?考虑没找到情况
	struct Node* frontNode = headNode;		//左
	struct Node* posNode = headNode->next;	//右
	//注意: && 短路处理
	//posNode != NULL作为找到表尾的退出条件
	//当posNode等于NULL ,NULL->data 的非法访问
	//frontNode->next!=NULL&&posNode->data != posData
	while (posNode != NULL && posNode->data != posData )//难点
	{
		//frontNode = frontNode->next;
		//posNode = posNode->next;
		frontNode = posNode;
		posNode = frontNode->next;  //posNode=posNode->next;
		//frontNode 是posNode左边
		//最后一节点:frontNode  posNode就是NULL
	}
	//退出循环,分析讨论是否找到
	if(posNode==NULL)
	{
		printf("%d\t", frontNode->data);
		printf("未找到,无法插入信息!\n");
	}
	else
	{
		struct Node* newNode = createNode(data);
		frontNode->next = newNode;
		newNode->next = posNode;
	}
}

在这里插入图片描述
删除操作:
打狗要看主人: 把一个节点下一个删除,要考虑删除节点上一节点next
不能删除NULL的东西

//6.表头删除
void deleteByHead(struct Node* headNode) 
{
	struct Node* nextNode = headNode->next;
	if (nextNode != NULL) //防御性编程
	{
		headNode->next = nextNode->next;
		free(nextNode);
		nextNode = NULL;
	}
}

在这里插入图片描述

//7.表尾删除
void deleteByTail(struct Node* headNode)
{
	struct Node* frontNode = NULL;
	struct Node* tailNode = headNode;  //NULL;
	//struct Node* tailNode = headNode->naxt;  会引发中断
	while (tailNode->next != NULL) //NULL->next!=NULL
	{
		frontNode = tailNode;
		tailNode = frontNode->next;
	}
	if (frontNode == NULL) 
	{
		printf("表为NULL,删除失败\n");
	}
	else 
	{
		frontNode->next = NULL;
		free(tailNode);
		tailNode = NULL;
	}
}
//8.指定位置删除
void deleteByAppoin(struct Node* headNode, int posData) 
{
	struct Node* frontNode = headNode;
	struct Node* posNode = headNode->next;
	while (posNode != NULL && posNode->data != posData) 
	{
		frontNode = posNode;
		posNode = frontNode->next;
	}
	if (posNode == NULL) 
	{
		printf("未找到,无法删除!\n");
	}
	else 
	{
		frontNode->next = posNode->next;
		free(posNode);
		posNode = NULL;
	}
}

在这里插入图片描述

//9.遍历--->打印
void printList(struct Node* headNode) 
{
	//为什么指向第二个节点? 因为第一个节点没有存数据
	struct Node* pMove = headNode->next;
	while (pMove != NULL) 
	{
		printf("%d\t", pMove->data);
		pMove = pMove->next;
	}
	printf("\n");
}
int main() 
{
	struct Node* list = createHead();
	for (int i = 0; i < 3; i++) 
	{
		insertByHead(list, i);
	}
	printList(list);
	insertByTail(list, 100);
	printList(list);
	insertByAppoin(list, 99, 100);
	printList(list);
	insertByAppoin(list, 102, 112122);
	insertByAppoin(list, 102, 2);
	printList(list);
	deleteByHead(list);
	printList(list);
	deleteByTail(list);
	printList(list);
	deleteByAppoin(list, 1);
	printList(list);
	return 0;
}

链表在项目当中的使用

链表:充当数据的容器
特点:灵活的存储数据
int date 改为 struct name date

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值