#C语言结构体/结构体指针/单链表学习必备总结(浓缩版)#

一.结构体的定义

结构体是一种用户自定义的数据类型,用于将多个不同类型的数据组合在一起形成一个新的数据类型。结构体由多个成员变量组成,每个成员变量可以是不同的数据类型,可以是基本数据类型(如整型、浮点型、字符型等)或其他结构体类型。结构体的成员变量在内存中是按照声明的顺序依次存储的。

1.结构体的声明初始化:

结构体是一种数据类型,也就是说可以用它来定义并且存储变量。

结构体是一种数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据、需要存储空间;

struct 结构体名 {

类型 成员1;

类型 成员2;

...

};

1.第一种方式:

struct   结构体名  结构体变量名;

#include <stdio.h>
struct date {
	int month;
	int year;
	int tall;
};
int main()
{
	struct date ax1;
	ax1.month = 5;
	ax1.tall = 180;
	ax1.year = 2024;

	struct date ax2 = { 5,2024,180 };

	struct date ax3 = { ax3.month = 5,ax3.year = 2024,ax3.tall = 180 };
	printf("%i\n%i\n%i\n", ax1.month, ax1.tall, ax1.year);
	printf("%i\n%i\n%i\n", ax2.month, ax2.tall, ax2.year);
	printf("%i\n%i\n%i\n", ax3.month, ax3.tall, ax3.year);
	return 0;
}
2.第二种方式:

struct 结构体名{

类型 成员;

类型 成员;
}结构体变量;

#include <stdio.h>
struct date {
	int month;
	int year;
	int tall;
}ax1,ax2,ax3;
int main()
{
//	struct date ax1;
	ax1.month = 5;
	ax1.tall = 180;
	ax1.year = 2024;

//	struct date ax2 = { 5,2024,180 };
	ax2={5,2024,180};

//	struct date ax3 = { ax3.month = 5,ax3.year = 2024,ax3.tall = 180 };
	ax3={ax3.month = 5,ax3.year = 2024,ax3.tall=100};
	
	
	printf("%i\n%i\n%i\n", ax1.month, ax1.tall, ax1.year);
	printf("%i\n%i\n%i\n", ax2.month, ax2.tall, ax2.year);
	printf("%i\n%i\n%i\n", ax3.month, ax3.tall, ax3.year);
	return 0;
}

2.结构体与指针的羁绊:

结构体类型指针访问成员的获取和赋值形式:

(1)(*p). 成员名(.的优先级高于*,(*p)两边括号不能少)

(2)   p->成员名(->指向符)

1.我们可以在结构体中存储指针:
#include <stdio.h>

struct Node
{
 int data;
 struct Node* next; 
}n1;
int main()
{
	n1={10,NULL};
	struct Node n2 = {20 , NULL};
	
	printf("%d %p\n",n1.data,n1.next);
	printf("%d %p",n2.data,n2.next);
	
	return 0;
}

2结构体类型也可以定义为结构体类型指针:
#include<stdio.h>

struct Inventory
{
	char description[10];
	int quantity;
};
int main()
{
	struct Inventory ax={"anxian",30
	};
	struct Inventory *stp=&ax;

	printf("%s %d\n", stp->description, stp->quantity);
	printf("%s %d\n", (*stp).description, (*stp).quantity);
	return 0;
}

3.与数据结构的羁绊

1.typedef----首先我们先介绍一个数据结构常客--

它的英文翻译是 “类型定义”。下面就来看看它的用法。

  typedef int anxian

此时我们就可以将anxian,来代表int这个数据类型。我们来看代码实现:

#include<stdio.h>
typedef int anxian;
int main()
{
	
	anxian a = 6;
	printf("%d",a);
	return 0;
}
2.在结构体中的使用:
typedef struct people {
	int age;
	char sex;
} chinese;

前面的是

typedef                        int                    anxian

而这里同理

typeddef             struct people           chinese

3.现在我们来看单链表
typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;		
} LinkNode;					

在这个单链表的结构体声明中,struct LNode表示链表的结点结构体,包含两个成员变量:

1.ElemType data:用于存储结点中的数据元素。在这里,ElemType 被定义为 int 类型,因此 data 是一个整型数据成员,用于存储结点中的数据。

2.struct LNode* next:指向后继结点的指针。这个成员变量是一个指针类型,指向下一个结点的地址。通过这个指针,可以实现链表中结点之间的连接,从而形成链表的数据结构。

因此,整体来看,这个单链表的结点结构体 struct LNode 包含了一个数据成员 data 用于存储数据,以及一个指针成员 next 用于指向下一个结点,从而实现链表中结点之间的连接。这种结构体嵌套结构体的方式,可以方便地表示链表的逻辑结构,使得链表的操作更加方便和灵活。

在这里我补充一点:

结构体里面是有一个数据域和一个指针域 是由数据类型和变量名构成。

 int                                  data

struct Lnode *                 next

#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;		//指向后继结点
} LinkNode;					//声明单链表结点类型
void CreateListF(LinkNode*& L, ElemType a[], int n)
//头插法建立单链表
{
	LinkNode* s;
	L = (LinkNode*)malloc(sizeof(LinkNode));  	//创建头结点
	L->next = NULL;
	for (int i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点s
		s->data = a[i];
		s->next = L->next;			//将结点s插在原开始结点之前,头结点之后
		L->next = s;
	}
}
void CreateListR(LinkNode*& L, ElemType a[], int n)
//尾插法建立单链表
{
	LinkNode* s, * r;
	L = (LinkNode*)malloc(sizeof(LinkNode));  	//创建头结点
	L->next = NULL;
	r = L;					//r始终指向终端结点,开始时指向头结点
	for (int i = 0; i < n; i++)
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点s
		s->data = a[i];
		r->next = s;			//将结点s插入结点r之后
		r = s;
	}
	r->next = NULL;			//终端结点next域置为NULL
}
void InitList(LinkNode*& L)
{
	L = (LinkNode*)malloc(sizeof(LinkNode));  	//创建头结点
	L->next = NULL;
}
void DestroyList(LinkNode*& L)
{
	LinkNode* pre = L, * p = pre->next;
	while (p != NULL)
	{
		free(pre);
		pre = p;
		p = pre->next;
	}
	free(pre);	//此时p为NULL,pre指向尾结点,释放它
}
bool ListEmpty(LinkNode* L)
{
	return(L->next == NULL);
}
int ListLength(LinkNode* L)
{
	LinkNode* p = L; int i = 0;
	while (p->next != NULL)
	{
		i++;
		p = p->next;
	}
	return(i);
}
void DispList(LinkNode* L)
{
	LinkNode* p = L->next;
	while (p != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}
bool GetElem(LinkNode* L, int i, ElemType& e)
{
	int j = 0;
	LinkNode* p = L;
	if (i <= 0) return false;		//i错误返回假
	while (j < i && p != NULL)
	{
		j++;
		p = p->next;
	}
	if (p == NULL)				//不存在第i个数据结点
		return false;
	else						//存在第i个数据结点
	{
		e = p->data;
		return true;
	}
}
int LocateElem(LinkNode* L, ElemType e)
{
	LinkNode* p = L->next;
	int n = 1;
	while (p != NULL && p->data != e)
	{
		p = p->next;
		n++;
	}
	if (p == NULL)
		return(0);
	else
		return(n);
}
bool ListInsert(LinkNode*& L, int i, ElemType e)
{
	int j = 0;
	LinkNode* p = L, * s;
	if (i <= 0)
		return false;			//i错误返回假
	while (j < i - 1 && p != NULL)		//查找第i-1个结点p
	{
		j++;
		p = p->next;
	}
	if (p == NULL)					//未找到位序为i-1的结点
		return false;
	else							//找到位序为i-1的结点*p
	{
		s = (LinkNode*)malloc(sizeof(LinkNode));//创建新结点*s
		s->data = e;
		s->next = p->next;			//将s结点插入到结点p之后
		p->next = s;
		return true;
	}
}
bool ListDelete(LinkNode*& L, int i, ElemType& e)
{
	int j = 0;
	LinkNode* p = L, * q;
	if (i <= 0)
		return false;		//i错误返回假
	while (j < i - 1 && p != NULL)	//查找第i-1个结点
	{
		j++;
		p = p->next;
	}
	if (p == NULL)				//未找到位序为i-1的结点
		return false;
	else						//找到位序为i-1的结点p
	{
		q = p->next;				//q指向要删除的结点
		if (q == NULL)
			return false;		//若不存在第i个结点,返回false
		e = q->data;
		p->next = q->next;		//从单链表中删除q结点
		free(q);				//释放q结点
		return true;
	}
}
int main()
{
	LinkNode* L;
	ElemType e;
	ElemType a[] = { 1,2,3,4 };
	CreateListF(L, a, 4);        //尾插法建立链表 
	printf("尾插法所得顺序为: ");
	DispList(L);
	DestroyList(L);
	CreateListR(L, a, 4);        //头插法建立链表 
	printf("头插法所得顺序为:");
	DispList(L);
	printf("链表的长度为:%d\n", ListLength(L));
	ListInsert(L, 4, 5);          //在链表第四个元素前插入5 
	printf("插入一个元素后链表的元素为:");
	DispList(L);
	ListDelete(L, 1, e);          //删除链表中第一个元素,并将它的值赋给e 
	printf("删除的元素为:%d\n", e);
	printf("删除一个元素后链表的元素为:");
	DispList(L);
	printf("当前链表是否为空:%d\n", ListEmpty(L));
	GetElem(L, 1, e);
	printf("链表第一个元素为:%d\n", e);
	printf("值为2的元素在链表中的位置为:%d\n", LocateElem(L, 2));
	return 0;
}

  • 28
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值