C的数据结构---带头结点的单链表

补充知识

结构体中嵌套结构体:

1.结构体中可以嵌套另一个结构体类型的数据

⒉结构体中可以嵌套指向自身的指针和指向另一个结构体的指针

3.结构体中不能嵌套自己类型的数据(无穷递归,确定不了数据类型的内存大小,分配不了内存)

链表

链表是一种物理存储单元上非连续的存储结构,由一系列(链表中每一个元素称为结点)组成,结点可以在运行时动态生成,结点与结点之间通过指针链接。每个结点包括两部分: 一部分是存储数据元素的数据域,另一部分是存储下一个结点地址的指针域

1). 链表是一种常用的数据结构,它通过指针将一系列数据结点,连接成一个数据链。相对于数组,链表具有更好的动态性

2).数据域用来存储数据,指针域用来建立与下一个结点的联系

3).建立链表时无需预先知道数据总量,可以随机的分配空间,可以高效的在链表中的任意位置实时插入或删除数据

带头单链表: 

静态带头单链表

缺点:固定结点个数

           结点的生命周期

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

typedef struct Teacher
{
	int data;
	Teacher *next;
}Teacher;
#include "Lead_Single_link_list.h"

int main()
{
	Teacher *head,t1,t2,t3,t4,t5;
	head = NULL;
	t1.data = 1;
	t2.data = 2;
	t3.data = 3;
	t4.data = 4;
	t5.data = 5;
	head = &t1;
	t1.next = &t2;
	t2.next = &t3;
	t3.next = &t4;
	t4.next = &t5;
	t5.next = NULL;
	while (head != NULL)
	{
		printf("%d ", head->data);
		head = head->next;  //指针下移
	}
	system("pause");
	return 0;
}

 

 动态带头单链表

 1. 不停的malloc新节点

 2. 新节点入链表

 3. 让新节点变成当前节点

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

typedef struct Node
{
	int data;
	Node *next;
}SList;

typedef struct BuyNode
{
	int data;
	Node *next;
}BuyNode;

SList* SList_Create();                              //创建链表

void SList_Print(SList*head);                        //打印链表

void SList_NodeInsert(SList*head, int x, int y);     //插入  在x前插入y

void SList_NodeDel(SList*head, int y);               //删除 y

void SList_Destory(SList*head);                      //销毁链表

#include "Lead_Single_link_list.h"


SList* SList_Create()
{
	SList*head = (SList*)malloc(sizeof(BuyNode));
	assert(head != NULL);
	//头结点初始化
	head->data = 0;
	head->next = NULL;
	SList*pCur = NULL;   //指向当前结点
	SList*pM = NULL;     //指向新购买的结点
	pCur = head;
	int data = 0;
	printf("请输入结点的数据!\n");
	scanf("%d", &data);
	while (data != -1)
	{
		pM = (SList*)malloc(sizeof(BuyNode));
		assert(pM != NULL);
		//购买的结点初始化
		pM->data = data;
		pM->next = NULL;
		//入链表
		pCur->next = pM;
		//新结点成为当前结点
		pCur = pM;

		printf("继续添加结点?\n");
		scanf("%d", &data);
	}
	return head;
}

void SList_Print(SList *head)
{
	assert(head != NULL);
	SList*tmp = head->next;
	while ( tmp!= NULL)
	{
		printf("%d ", tmp->data);
		tmp = tmp->next;
	}
	printf("\n");
}

void SList_NodeInsert(SList *head, int x, int y)
{
	assert(head != NULL);
	SList *pPre = head;                 //前驱指针
	SList *pCur = head->next;           //当前指针
	SList *pM = NULL;                   //新结点指针
	pM = (SList*)malloc(sizeof(SList));
	assert(pM != NULL);
	//新节点初始化
	pM->data = y;
	pM->next = NULL;
	//寻找新结点插入链表的位置
	while (pCur != NULL)
	{
		if (pCur->data == x)
		{
			break;
		}
		pPre = pCur;
		pCur = pCur->next;
	}
	//新节点插入链表
	//如果没找到插入位置,结点则会添加到链表的末尾
	pM->next = pPre->next; //新节点先链接后继
	pPre->next = pM;       //新节点后链接前驱
}

void SList_NodeDel(SList*head, int y)
{
	assert(head != NULL);
	SList *pPer = head;
	SList *pCur = head->next;
	while (pCur != NULL)
	{
		if (pCur->data == y)
		{
			break;
		}
		pPer = pCur;
		pCur = pCur->next;
	}
	if (pCur == NULL)
	{
		printf("没有找到结点值为: %d 的结点\n", y);
		return;
	}
	else
	{
		pPer->next = pCur->next;
		free(pCur);
		pCur = NULL;
	}
}

void SList_Destory(SList*head)
{
	SList*tmp = NULL;
	while (head != NULL)
	{
		tmp = head->next;
		free(head);
		head = tmp;
	}
}

int main()
{
	SList*head = SList_Create();
	SList_Print(head);
	SList_NodeInsert(head, 12, 11);
	SList_Print(head);
	SList_NodeDel(head, 11);
	SList_Print(head);
	SList_Destory(head);
	system("pause");
	return 0;
}

借助三个辅助指针来实现

图解

pM指针对新购买的结点进行初始化,初始化完成后将结点的地址给pCur指向的当前结点的next指针和pCur的本身,使得*next和pCur都能指向新节点,新节点完成入链表和成为当前结点的两个动作

插入新节点

未找到则会插入链表末尾

 插入链表的三种情况

删除某个结点:


单链表逆置

void SList_Inversion(SList*head)
{
	//链表为空,只有一个结点,只有两个结点都不要逆置
	assert(head != NULL || head->next != NULL || head->next->next != NULL);
	//初始化
	SList*p = head->next;
	SList*q = p->next;
	SList*t = NULL;
	//一个结点一个结点的逆置
	while (q != NULL)
	{
		t = q->next;  //缓存后面的结点
		q->next = p;  //逆置
		p = q;        //让p移动到下一个结点
		q = t;        //让q移动到下一个结点
	}
	head->next->next = NULL;
	head->next = p;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值