数据结构学习(C语言)之链表代码

本文深入讲解链表数据结构,涵盖链表的创建、遍历、排序、插入、删除等核心算法,通过具体代码实例帮助读者理解算法实现及泛型概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(郝斌老师视频课)

简介:

24_链表创建和链表遍历算法的演示
25_判断链表是否为空和求链表长度算法的演示
26_通过链表排序算法的演示再次详细讨论到底什么是算法以及到底什么是泛型【重点】
27_如何学习算法自己的一些感想
28_链表插入和删除算法的演示
29_复习

24_链表创建和链表遍历算法的演示

创建一个节点的结构体

typedef struct Node
{
	int data;//数据域
	struct Node * pNext;//指针域
}NODE,*PNODE;//NODE等价于struct Node,PNODE等价于struct Node *

创建链表函数

PNODE create_list(void)
{
	int len;//用来存放有效节点的个数
	int i;
	int val;//用来临时存放用户输入的节点的值

	//分配了一个不存放有效数据的头节点
	PNODE pHead=(PNODE)malloc(sizeof(NODE));
	if(NULL==pHead)
	{
		printf("分配失败,程序终止!\n");
		exit(-1);
	}
	PNODE pTail=pHead;
	pTail->pNext=NULL;
	printf("请输入您需要生成的链表节点的个数:len=");
	scanf("%d",&len);

	for (i=0;i<len;i++)
	{
		printf("请输入第%d个节点的值:",i+1);
		scanf("%d",&val);

		PNODE pNew=(PNODE)malloc(sizeof(NODE));
		if(NULL==pNew)
		{
			printf("分配失败,程序终止!\n");
			exit(-1);
		}
		pNew->data=val;//挂
		pTail->pNext=pNew;
		pNew->pNext=NULL;
		pTail=pNew;
	}
	return pHead;
}

链表遍历

void traverse_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	while(NULL!=p)
	{
		printf("%d ",p->data);	
		p=p->pNext;//不连续,不能用p++
	}
	printf("\n");
	return;
}

测试

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

typedef struct Node
{
	int data;//数据域
	struct Node * pNext;//指针域
}NODE,*PNODE;//NODE等价于struct Node,PNODE等价于struct Node *
//函数声明
PNODE create_list(void);
void traverse_list(PNODE pHead);

int main(void)
{
	PNODE pHead=NULL;//等价于struct Node *pHead=NULL;
	pHead=create_list();//creat_list()功能:创建一个非循环单链表,并将该链表的头节点的地址付给pHead
	traverse_list(pHead);
	return 0;
}

PNODE create_list(void)
{
	int len;//用来存放有效节点的个数
	int i;
	int val;//用来临时存放用户输入的节点的值

	//分配了一个不存放有效数据的头节点
	PNODE pHead=(PNODE)malloc(sizeof(NODE));
	if(NULL==pHead)
	{
		printf("分配失败,程序终止!\n");
		exit(-1);
	}
	PNODE pTail=pHead;
	pTail->pNext=NULL;
	printf("请输入您需要生成的链表节点的个数:len=");
	scanf("%d",&len);

	for (i=0;i<len;i++)
	{
		printf("请输入第%d个节点的值:",i+1);
		scanf("%d",&val);

		PNODE pNew=(PNODE)malloc(sizeof(NODE));
		if(NULL==pNew)
		{
			printf("分配失败,程序终止!\n");
			exit(-1);
		}
		pNew->data=val;//挂
		pTail->pNext=pNew;
		pNew->pNext=NULL;
		pTail=pNew;
	
	}
	return pHead;
}

void traverse_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	while(NULL!=p)
	{
		printf("%d ",p->data);	
		p=p->pNext;//不连续,不能用p++
	}
	printf("\n");
	return;
}

在这里插入图片描述

25_判断链表是否为空和求链表长度算法的演示

判断链表是否为空

bool is_empty(PNODE pHead)
{
	if(pHead->pNext==NULL)
		return true;
	else
		return false;
}

求链表长度

int length_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	int len=0;
	while(NULL!=p)
	{
		len++;
		p=p->pNext;
	}
	return len;
}

测试:

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

typedef struct Node
{
	int data;//数据域
	struct Node * pNext;//指针域
}NODE,*PNODE;//NODE等价于struct Node,PNODE等价于struct Node *
//函数声明
PNODE create_list(void);
void traverse_list(PNODE pHead);
bool is_empty(PNODE pHead);
int length_list(PNODE);
bool insert_list(PNODE,int,int);
bool delete_list(PNODE,int,int*);
void sort_list(PNODE);


int main(void)
{
	PNODE pHead=NULL;//等价于struct Node *pHead=NULL;
	pHead=create_list();//creat_list()功能:创建一个非循环单链表,并将该链表的头节点的地址付给pHead
	traverse_list(pHead);
	int len=length_list(pHead);
	printf("链表长度是%d\n",len);

	if(is_empty(pHead))
		printf("链表为空!\n");
	else 
		printf("链表不空!\n");

	return 0;
}

PNODE create_list(void)
{
	int len;//用来存放有效节点的个数
	int i;
	int val;//用来临时存放用户输入的节点的值

	//分配了一个不存放有效数据的头节点
	PNODE pHead=(PNODE)malloc(sizeof(NODE));
	if(NULL==pHead)
	{
		printf("分配失败,程序终止!\n");
		exit(-1);
	}
	PNODE pTail=pHead;
	pTail->pNext=NULL;
	printf("请输入您需要生成的链表节点的个数:len=");
	scanf("%d",&len);

	for (i=0;i<len;i++)
	{
		printf("请输入第%d个节点的值:",i+1);
		scanf("%d",&val);

		PNODE pNew=(PNODE)malloc(sizeof(NODE));
		if(NULL==pNew)
		{
			printf("分配失败,程序终止!\n");
			exit(-1);
		}
		pNew->data=val;//挂
		pTail->pNext=pNew;
		pNew->pNext=NULL;
		pTail=pNew;
	
	}
	return pHead;
}

void traverse_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	while(NULL!=p)
	{
		printf("%d ",p->data);	
		p=p->pNext;//不连续,不能用p++
	}
	printf("\n");
	return;
}

bool is_empty(PNODE pHead)
{
	if(pHead->pNext==NULL)
		return true;
	else
		return false;
}

int length_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	int len=0;
	while(NULL!=p)
	{
		len++;
		p=p->pNext;
	}
	return len;
}

在这里插入图片描述
在这里插入图片描述

26_通过链表排序算法的演示再次详细讨论到底什么是算法以及到底什么是泛型【重点】

算法
狭义的算法是与数据的存储方式密切相关
广义的算法是与数据的存储方式无关
泛型
利用某种技术达到的效果就是:不同的存储方式,执行的操作是一样的
排序
在这里插入图片描述

void sort_list(PNODE pHead)
{
	int i,j,t;
	int len=length_list(pHead);
	PNODE p,q;
	for(i=0,p=pHead->pNext;i<len-1;++i,p=p->pNext)
	{
		for(j=i+1,q=p->pNext;j<len;++j,q=q->pNext)
		{
			if(p->data>q->data)//类似于数组中的:a[i]>a[j]
			{
				t=p->data;//类似于数组中的:	t=a[i];
				p->data=q->data;//类似于数组中的:	a[i]=a[j];
				q->data=t;//类似于数组中的:	a[j]=t;
			}
		}
	}

}

测试:

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

typedef struct Node
{
	int data;//数据域
	struct Node * pNext;//指针域
}NODE,*PNODE;//NODE等价于struct Node,PNODE等价于struct Node *
//函数声明
PNODE create_list(void);
void traverse_list(PNODE pHead);
bool is_empty(PNODE pHead);
int length_list(PNODE);
bool insert_list(PNODE,int,int);
bool delete_list(PNODE,int,int*);
void sort_list(PNODE);


int main(void)
{
	PNODE pHead=NULL;//等价于struct Node *pHead=NULL;
	pHead=create_list();//creat_list()功能:创建一个非循环单链表,并将该链表的头节点的地址付给pHead
	traverse_list(pHead);
	int len=length_list(pHead);
	printf("链表长度是%d\n",len);

	if(is_empty(pHead))
		printf("链表为空!\n");
	else 
		printf("链表不空!\n");
	sort_list(pHead);
	traverse_list(pHead);


	return 0;
}

PNODE create_list(void)
{
	int len;//用来存放有效节点的个数
	int i;
	int val;//用来临时存放用户输入的节点的值

	//分配了一个不存放有效数据的头节点
	PNODE pHead=(PNODE)malloc(sizeof(NODE));
	if(NULL==pHead)
	{
		printf("分配失败,程序终止!\n");
		exit(-1);
	}
	PNODE pTail=pHead;
	pTail->pNext=NULL;
	printf("请输入您需要生成的链表节点的个数:len=");
	scanf("%d",&len);

	for (i=0;i<len;i++)
	{
		printf("请输入第%d个节点的值:",i+1);
		scanf("%d",&val);

		PNODE pNew=(PNODE)malloc(sizeof(NODE));
		if(NULL==pNew)
		{
			printf("分配失败,程序终止!\n");
			exit(-1);
		}
		pNew->data=val;//挂
		pTail->pNext=pNew;
		pNew->pNext=NULL;
		pTail=pNew;
	
	}
	return pHead;
}

void traverse_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	while(NULL!=p)
	{
		printf("%d ",p->data);	
		p=p->pNext;//不连续,不能用p++
	}
	printf("\n");
	return;
}

bool is_empty(PNODE pHead)
{
	if(pHead->pNext==NULL)
		return true;
	else
		return false;
}

int length_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	int len=0;
	while(NULL!=p)
	{
		len++;
		p=p->pNext;
	}
	return len;
}

void sort_list(PNODE pHead)
{
	int i,j,t;
	int len=length_list(pHead);
	PNODE p,q;
	for(i=0,p=pHead->pNext;i<len-1;++i,p=p->pNext)
	{
		for(j=i+1,q=p->pNext;j<len;++j,q=q->pNext)
		{
			if(p->data>q->data)//类似于数组中的:a[i]>a[j]
			{
				t=p->data;//类似于数组中的:	t=a[i];
				p->data=q->data;//类似于数组中的:	a[i]=a[j];
				q->data=t;//类似于数组中的:	a[j]=t;
			}
		}
	}
}

在这里插入图片描述

27_如何学习算法自己的一些感想

28_链表插入和删除算法的演示

插入

//在pHead所指向链表的第pos个节点的前面插入一个新的节点,新节点的值是val,并且pos的值是从1开始
bool insert_list(PNODE pHead,int pos,int val)
{
	int i=0;
	PNODE p=pHead;

	while(NULL!=p&&i<pos-1)
	{
		p=p->pNext;
		++i;
	}
	if(i>pos-1||NULL==p)  //这句话可以排除所有意外情况
		return false;
	PNODE pNew=(PNODE)malloc(sizeof(NODE));
	if(NULL==pNew)
	{
		printf("动态分配内存失败!\n");
		exit(-1);
	}
	pNew->data=val;

	PNODE q=p->pNext;   //定义一个临时节点
	p->pNext=pNew;
	pNew->pNext=q;
	return true;

}

删除

bool delete_list(PNODE pHead,int pos,int* pVal)
{
	int i=0;
	PNODE p=pHead;

	while(NULL!=p->pNext&&i<pos-1)
	{
		p=p->pNext;
		++i;
	}
	if(i>pos-1||NULL==p->pNext)
		return false;
	PNODE q=p->pNext;
	*pVal=q->data;
	//删除p节点后面的节点
	p->pNext=p->pNext->pNext;
	free(q);
	q=NULL;
}

测试:

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

typedef struct Node
{
	int data;//数据域
	struct Node * pNext;//指针域
}NODE,*PNODE;//NODE等价于struct Node,PNODE等价于struct Node *
//函数声明
PNODE create_list(void);
void traverse_list(PNODE pHead);
bool is_empty(PNODE pHead);
int length_list(PNODE);
bool insert_list(PNODE,int,int);
bool delete_list(PNODE,int,int*);
void sort_list(PNODE);


int main(void)
{
	PNODE pHead=NULL;//等价于struct Node *pHead=NULL;
	int val;
	pHead=create_list();//creat_list()功能:创建一个非循环单链表,并将该链表的头节点的地址付给pHead
	traverse_list(pHead);
	int len=length_list(pHead);
	printf("链表长度是%d\n",len);

	if(is_empty(pHead))
		printf("链表为空!\n");
	else 
		printf("链表不空!\n");
	sort_list(pHead);
	traverse_list(pHead);
	insert_list(pHead,4,33);
	traverse_list(pHead);
	if (delete_list(pHead,4,&val))
	{
		printf("删除成功,您删除的元素是:%d\n",val);
	}
	else
	{
		printf("删除失败!您删除的元素不存在!\n");
	}
	traverse_list(pHead);

	return 0;
}

PNODE create_list(void)
{
	int len;//用来存放有效节点的个数
	int i;
	int val;//用来临时存放用户输入的节点的值

	//分配了一个不存放有效数据的头节点
	PNODE pHead=(PNODE)malloc(sizeof(NODE));
	if(NULL==pHead)
	{
		printf("分配失败,程序终止!\n");
		exit(-1);
	}
	PNODE pTail=pHead;
	pTail->pNext=NULL;
	printf("请输入您需要生成的链表节点的个数:len=");
	scanf("%d",&len);

	for (i=0;i<len;i++)
	{
		printf("请输入第%d个节点的值:",i+1);
		scanf("%d",&val);

		PNODE pNew=(PNODE)malloc(sizeof(NODE));
		if(NULL==pNew)
		{
			printf("分配失败,程序终止!\n");
			exit(-1);
		}
		pNew->data=val;//挂
		pTail->pNext=pNew;
		pNew->pNext=NULL;
		pTail=pNew;
	
	}
	return pHead;
}

void traverse_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	while(NULL!=p)
	{
		printf("%d ",p->data);	
		p=p->pNext;//不连续,不能用p++
	}
	printf("\n");
	return;
}

bool is_empty(PNODE pHead)
{
	if(pHead->pNext==NULL)
		return true;
	else
		return false;
}

int length_list(PNODE pHead)
{
	PNODE p=pHead->pNext;
	int len=0;
	while(NULL!=p)
	{
		len++;
		p=p->pNext;
	}
	return len;
}

void sort_list(PNODE pHead)
{
	int i,j,t;
	int len=length_list(pHead);
	PNODE p,q;
	for(i=0,p=pHead->pNext;i<len-1;++i,p=p->pNext)
	{
		for(j=i+1,q=p->pNext;j<len;++j,q=q->pNext)
		{
			if(p->data>q->data)//类似于数组中的:a[i]>a[j]
			{
				t=p->data;//类似于数组中的:	t=a[i];
				p->data=q->data;//类似于数组中的:	a[i]=a[j];
				q->data=t;//类似于数组中的:	a[j]=t;
			}
		}
	}

}

//在pHead所指向链表的第pos个节点的前面插入一个新的节点,新节点的值是val,并且pos的值是从1开始
bool insert_list(PNODE pHead,int pos,int val)
{
	int i=0;
	PNODE p=pHead;

	while(NULL!=p&&i<pos-1)
	{
		p=p->pNext;
		++i;
	}
	if(i>pos-1||NULL==p)  //这句话可以排除所有意外情况
		return false;
	PNODE pNew=(PNODE)malloc(sizeof(NODE));
	if(NULL==pNew)
	{
		printf("动态分配内存失败!\n");
		exit(-1);
	}
	pNew->data=val;

	PNODE q=p->pNext;   //定义一个临时节点
	p->pNext=pNew;
	pNew->pNext=q;
	return true;

}

bool delete_list(PNODE pHead,int pos,int* pVal)
{
	int i=0;
	PNODE p=pHead;

	while(NULL!=p->pNext&&i<pos-1)
	{
		p=p->pNext;
		++i;
	}
	if(i>pos-1||NULL==p->pNext)
		return false;
	PNODE q=p->pNext;
	*pVal=q->data;
	//删除p节点后面的节点
	p->pNext=p->pNext->pNext;
	free(q);
	q=NULL;

}

在这里插入图片描述

29_复习

数据结构
狭义
数据结构是专门研究数据存储的问题
数据的存储包含两方面:个体的存储+个体关系的存储
广义
数据结构既包括数据的存储也包括数据的操作
对存储数据的操作就是算法
算法
狭义
算法是和数据的存储方式密切相关
广义
算法和数据的存储方式无关
这就是泛型思想

数据的存储方式有几种
1、线性
(1)连续存储【数组】
优点
存取速度很快
缺点
事先需要知道数组的长度
插入删除元素很慢
空间通常有限制
需要大块连续的内存块

(2)离散存储【链表】
优点
空间没有限制
插入删除元素很快
缺点
存取速度很慢
2、非线性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值