数据结构:2.链式表

几乎全是代码,概念配合代码,可以多打几遍熟练

目录

1.链表分类

2.单向链表

3.双向链表

4.循环链表

5.数组和链表的区别


1.链表分类

  • 单向链表
  • 双向链表
  • 循环链表

2.单向链表

  • 单向链表又分有头链表和无头链表
  • 有头链表(又称带头节点的链表)是在链表的第一个元素之前增加一个特殊的"头节点",这个节点不存储实际数据,只作为链表的入口
  • 无头链表是指链表的第一个节点就是实际存储数据的节点,没有额外的头节点
  • 由于无头链表要用到大量二级指针,过于麻烦,有头链表更为常用
  • 多文件编程makefile

makefile

mu:=main
lai+=lian.c
lai+=main.c
$(mu):$(lai)
    gcc $^ -g -o $@                                                         

.PHONY:
clean:
    rm $(mu)
//查看是否有内存泄漏
cha:
    valgrind --tool=memcheck --leak-check=full ./$(mu)

下为单向链表的创建,插入值(头插),打印,删除值,寻找值,修改值,插入值(尾插),销毁链表,查找中间节点,查找倒数第n个,倒置链表,冒泡排序,选择排序,lian.c文件

#include"lian.h"
Node_t *chuanglian(void)
{
	Node_t *pnewnode = NULL;
	pnewnode = malloc(sizeof(Node_t));
	if(NULL == pnewnode)
	{
		perror("失败");
		return NULL;
	}
	pnewnode->pnext = NULL;

	return pnewnode;
}
int chalian(Node_t *ptou,datatype data)
{
	Node_t *pnewnode = NULL;
	pnewnode = malloc(sizeof(Node_t));
	if(NULL == pnewnode)
	{
		perror("失败");
		return -1;
	}
	pnewnode->data = data;
	pnewnode->pnext = ptou->pnext;
	ptou->pnext = pnewnode;
	return 0;
}
void showlian(Node_t *ptou)
{
	Node_t * pzhong = NULL;
	pzhong = ptou->pnext;
	while(pzhong != NULL)
	{
		printf("%d ",pzhong->data);
		pzhong = pzhong->pnext;
	}
	putchar('\n');
}
int shanlian(Node_t *ptou,datatype a)
{
	int cnt = 0;
	Node_t *pqian = NULL;
	Node_t *phou = NULL;
	pqian = ptou->pnext;
	phou = ptou;
	while(pqian != NULL)
	{
		if(pqian->data == a)
		{
			phou->pnext = pqian->pnext;
			free(pqian);
			pqian = phou->pnext; 
			cnt++;
		}
		else
		{
			pqian = pqian->pnext;
			phou = phou->pnext;
		}
	}
	return cnt;
}
Node_t * zhaolian(Node_t *ptou,datatype a)
{
	Node_t *pzhong = NULL;
	Node_t *pfu = NULL;
	pzhong = ptou->pnext;
	while(pzhong != NULL)
	{
		if(a == pzhong->data)
		{
			pfu = pzhong;
			return pfu;
		}
		pzhong = pzhong->pnext;
	}
	return NULL;
}
int gailian(Node_t *ptou,datatype jiu,datatype xin)
{
	int cnt = 0;
	Node_t *pzhong = NULL;
	pzhong = ptou->pnext;
	while(pzhong != NULL)
	{
		if(pzhong->data==jiu)
		{
			pzhong->data = xin;
			cnt++;
		}
		pzhong = pzhong->pnext;
	}
	return cnt;
}
int weichalian(Node_t *ptou,datatype data)
{
	Node_t *pnewnode = NULL;
	//如果Node_t *pzhong = ptou;当只有一个头时,会出现段错误,NULL
	Node_t *pzhong = ptou;
	pnewnode = malloc(sizeof(Node_t));
	if(NULL == pnewnode)
	{
		perror("失败");
		return -1;
	}
	pnewnode->data = data;
	while(pzhong->pnext != NULL)
	{
		pzhong=pzhong->pnext;
	}
	//此时,pzhong->pnext == NULL
	pnewnode->pnext = NULL;//pnewnode->pnext = pzhong->pnext;
	pzhong->pnext = pnewnode;
	return 0;
}
void hui(Node_t **pptou)
{
	Node_t *pqian = NULL;
	Node_t *phou = NULL;
	pqian = *pptou;
	phou = *pptou;
	while(pqian != NULL)
	{
		pqian = pqian->pnext;
		free(phou);
		phou = pqian;
	}
	*pptou = NULL;
}
Node_t *zhaozhlian(Node_t *ptou)
{
	Node_t *pkuai = NULL;
	Node_t *pman = NULL;
	pkuai = pman = ptou->pnext;
	while(pkuai != NULL)
	{
		pkuai = pkuai->pnext;
		if(pkuai == NULL)
		{
			return pman;
		}
		pkuai = pkuai->pnext;
		pman = pman->pnext;
	}
	return pman;
}
Node_t *zhaoalian(Node_t *ptou,int a)
{
	Node_t *pkuai = NULL;
	Node_t *pman = NULL;
	pkuai = pman = ptou->pnext;
	int x = 0;
	for(x = 0;x<a && pkuai!=NULL;x++)
	{
		pkuai = pkuai->pnext;
	}
	while(pkuai != NULL)
	{
		pkuai = pkuai->pnext;
		pman = pman->pnext;
	}
	return pman;
}
void daozhilian(Node_t *ptou)
{
	Node_t *pqian = NULL;
	Node_t *phou = NULL;
	pqian = phou = ptou->pnext;
	ptou->pnext = NULL;
	while(pqian != NULL)
	{
		pqian = pqian->pnext;
		phou->pnext = ptou->pnext;
		ptou->pnext = phou;
		phou = pqian;

	}
}
int maopaolian(Node_t *ptou)
{
	Node_t *pqian = NULL;
	Node_t *phou = NULL;
	Node_t *pend = NULL;
	datatype zhong;
	if(ptou->pnext==NULL || ptou->pnext->pnext==NULL )
		return 0;
	while(1)
	{
		pqian = ptou->pnext->pnext;
		phou = ptou->pnext;
		if(pend == pqian)
			break;
		while(pqian != pend)
		{
			if(pqian->data < phou->data)
			{
				zhong = phou->data;
				phou->data = pqian->data;
				pqian->data = zhong;
			}
			pqian = pqian->pnext;
			phou = phou->pnext;
		}
		pend = phou;
	}
	return 0;
}
int xuanzelian(Node_t *ptou)
{
	Node_t *pqian = NULL;
	Node_t *phou = NULL;
	Node_t *pmax = NULL;
	datatype zhong;
	if(ptou->pnext==NULL || ptou->pnext->pnext==NULL )
		return 0;
	phou = ptou->pnext;
	while(phou->pnext != NULL)
	{
		pqian = phou->pnext;
		pmax = phou;
		while(pqian != NULL)
		{
			if(pmax->data < pqian->data)
				pmax = pqian;
			pqian = pqian->pnext;
		}
		if(pmax->data != phou->data)
		{
			zhong = phou->data;
			phou->data = pmax->data;
			pmax->data = zhong;
		}
		phou = phou->pnext;
	}
	return 0;
}

main.c文件

#include"lian.h"
int main()
{
	Node_t *plian = NULL;
	plian = chuanglian();
	Node_t *pliana = chuanglian();
	chalian(plian,1);
	chalian(plian,2);
	chalian(plian,3);
	chalian(plian,3);
	chalian(plian,4);
	chalian(plian,2);
	chalian(plian,5);
	printf("头插:1、2、3、3、4、2、5\n");
	showlian(plian);
	int a=shanlian(plian,3);
	printf("删了%d个3\n",a);
	showlian(plian);
	Node_t *fu = zhaolian(plian,4);
	printf("找4:%p %d \n",fu,fu->data);
	int b=gailian(plian,2,9);
	printf("9换2:");
	showlian(plian);
	weichalian(plian,0);
	weichalian(plian,1);
	weichalian(plian,2);
	weichalian(plian,3);
	weichalian(plian,4);
	weichalian(plian,5);
	printf("尾插:0、1、2、3、4、5\n");
	showlian(plian);
	maopaolian(plian);
	printf("lian冒泡排序:");
	showlian(plian);
	xuanzelian(plian);
	printf("lian选择排序:");
	showlian(plian);
	weichalian(pliana,0);
	weichalian(pliana,1);
	weichalian(pliana,2);
	weichalian(pliana,3);
	weichalian(pliana,4);
	weichalian(pliana,5);
	printf("尾插:0、1、2、3、4、5\n");
	showlian(pliana);
	daozhilian(pliana);
	printf("倒置:");
	showlian(pliana);
	fu = zhaozhlian(pliana);
	printf("pliana中间:%d\n",fu->data);
	fu = zhaoalian(pliana,2);
	printf("pliana倒数第二个值:%d\n",fu->data);
	hui(&plian);
	printf("lian = %p\n",plian);
	hui(&pliana);
	printf("liana = %p\n",pliana);
	return 0;
}

lian.h文件

#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include<stdio.h>
#include<stdlib.h>
typedef int datatype;
typedef struct node
{
	datatype data;
	struct node *pnext;
}Node_t;
//创建链表
extern Node_t *chuanglian(void);
//插入值(头插)
extern int chalian(Node_t *ptou,datatype data);
//打印链表
extern void showlian(Node_t *ptou);
//删除值
extern int shanlian(Node_t *ptou,datatype a);
//查找值
extern Node_t *zhaolian(Node_t *ptou,datatype a);
//修改值
extern int gailian(Node_t *ptou,datatype jiu,datatype xin);
//插入值(尾插)
extern int weichalian(Node_t *ptou,datatype data);
//销毁链表
extern void hui(Node_t **pptou);
//找中间值
extern Node_t *zhaozhlian(Node_t *ptou);
//找倒数第a个值
extern Node_t *zhaoalian(Node_t *ptou,int a);
//倒置链表
extern void daozhilian(Node_t *ptou);
//冒泡排序
extern int maopaolian(Node_t *ptou);
//选择排序
extern int xuanzelian(Node_t *ptou);
#endif

3.双向链表

下为双向链表的创建,插入值(头插),插入值(尾插),打印,删除值,寻找值,修改值,销毁链表,lian.c文件

#include"lian.h"
lian *chuanglian(void)
{
	lian *ptou = malloc(sizeof(lian));
	if(ptou == NULL)
	{
		perror("失败");
		return NULL;
	}
	ptou->zhens = NULL;
	ptou->zhenx = NULL;
	return ptou;
}
int chalian(lian *ptou,type a)
{
	lian *pnew = malloc(sizeof(lian));
	if(pnew == NULL)
	{
		perror("失败");
		return -1;
	}
	pnew->zhi = a;
	if(ptou->zhenx != NULL)
		ptou->zhenx->zhens = pnew;
	pnew->zhenx = ptou->zhenx;
	pnew->zhens = ptou;
	ptou->zhenx = pnew;
	return 0;
}
int weilian(lian *ptou,type a)
{
	lian *pnew = malloc(sizeof(lian));
	lian *pzh = ptou;
	if(pnew == NULL)
	{
		perror("失败");
		return -1;
	}
	while(pzh->zhenx != NULL)
	{
		pzh = pzh->zhenx;
	}
	pnew->zhi = a;
	pnew->zhenx = NULL;
	pzh->zhenx = pnew;
	pnew->zhens = pzh;
	return 0;
}
int showlian(lian *ptou)
{
	lian *pzh = ptou->zhenx;
	while(pzh != NULL)
	{
		printf("%d ",pzh->zhi);
		pzh = pzh->zhenx;
	}putchar('\n');
	return 0;
}
int shanlian(lian *ptou,type a)
{
	lian *pzh = ptou->zhenx;
	lian *pfree = NULL;
	int cnt = 0;
	while(pzh != NULL)
	{
		if(a == pzh->zhi)
		{
			pzh->zhens->zhenx = pzh->zhenx;
			if(pzh->zhenx != NULL)
				pzh->zhenx->zhens = pzh->zhens;
			pfree = pzh;
			pzh = pzh->zhenx;
			free(pfree);
			pfree = NULL;
			cnt++;
		}
		else
			pzh = pzh->zhenx;
	}
	return cnt;
}
void gailian(lian *ptou,type xin,type jiu)
{
	lian *pzh = ptou->zhenx;
	while(pzh != NULL)
	{
		if(pzh->zhi == jiu)
			pzh->zhi = xin;
		pzh = pzh->zhenx;
	}
}
lian *zhaolian(lian *ptou,type a)
{
	lian *pzh = ptou->zhenx;
	while(pzh != NULL)
	{
		if(pzh->zhi == a)
			return pzh;
		pzh = pzh->zhenx;
	}
	return NULL;
}
int huilian(lian **pptou)
{
	lian *pqian = *pptou;
	lian *phou = *pptou;
	while(pqian != NULL)
	{
		pqian = pqian->zhenx;
		free(phou);
		phou = pqian;
	}
	*pptou = NULL;
	return 0;
}

main.c

#include"lian.h"
int main(void)
{
	lian *nian = chuanglian();
	lian *year = chuanglian();
	int a = 0;
	
	chalian(nian,1);
	chalian(nian,3);
	chalian(nian,0);
	chalian(nian,0);
	chalian(nian,5);
	chalian(nian,7);
	chalian(nian,9);
	chalian(nian,2);
	chalian(nian,0);
	chalian(nian,4);
	chalian(nian,6);
	printf("nain头插:1 3 0 0 5 7 9 2 0 4 6\n");
	showlian(nian);
	weilian(year,0);
	weilian(year,1);
	weilian(year,2);
	weilian(year,3);
	weilian(year,4);
	weilian(year,5);
	printf("year尾插:0 1 2 3 4 5\n");
	showlian(year);
	a = shanlian(nian,0);
	printf("nian删了%d个0\n",a);
	showlian(nian);
	gailian(nian,0,2);
	printf("nian2改0:");
	showlian(nian);
	lian *niana = zhaolian(nian,9);
	printf("nian找9:%d %p\n",niana->zhi,niana);
	printf("nian未销毁:%p\n",nian);
	printf("year未销毁:%p\n",year);
	huilian(&nian);
	huilian(&year);
	printf("nian销毁:%p\n",nian);
	printf("year销毁:%p\n",year);
	return 0;
}

lian.h

#ifndef __LIAN_H__
#define __LIAN_H__
#include<stdio.h>
#include<stdlib.h>

typedef int type;
typedef struct lian
{
	struct lian *zhens;
	type zhi;
	struct lian *zhenx;
}lian;
//创建双向链表
extern lian *chuanglian(void);
//头插法
extern int chalian(lian*ptou,type a);
//尾插法
extern int weilian(lian*ptou,type a);
//打印双向链表
extern int showlian(lian *ptou);
//删除某值
extern int shanlian(lian *ptou,type a);
//改变某值
extern void gailian(lian *ptou,type xin,type jiu);
//寻找某值
extern lian *zhaolian(lian *ptou,type a);
//销毁双向链表
extern int huilian(lian **pptou);
#endif

4.循环链表

下为循环链表的创建,插入值(头插),插入值(尾插),打印,删除值,销毁链表,lian.c文件

#include"lian.h"
xun *chuanglian(void)
{
	xun *ptou = malloc(sizeof(xun));
	if(ptou == NULL)
	{
		perror("失败");
		return NULL;
	}
	ptou->zhens = ptou;
	ptou->zhenx = ptou;
	return ptou;
}
int chalian(xun *ptou,type a)
{
	xun *pnew = malloc(sizeof(xun));
	if(pnew == NULL)
	{
		perror("失败");
		return -1;
	}
	pnew->zhi = a;
	pnew->zhenx = ptou->zhenx;
	ptou->zhenx = pnew;
	pnew->zhenx->zhens = pnew;
	pnew->zhens = ptou; 
	return 0;
}
int weilian(xun *ptou,type a)
{
	xun *pnew = malloc(sizeof(xun));
	if(pnew == NULL)
	{
		perror("失败");
		return -1;
	}
	pnew->zhi = a;
	pnew->zhenx = ptou;
	pnew->zhens = ptou->zhens;
	ptou->zhens = pnew;
	pnew->zhens->zhenx = pnew;
	return 0;
}
int showlian(xun *ptou)
{
	xun *pzh = ptou->zhenx;
	while(pzh != ptou)
	{
		printf("%d ",pzh->zhi);
		pzh = pzh->zhenx;
	}putchar('\n');
	return 0;
}

int Deletecycle(xun *pHead,type a)
{
	xun *pzh = NULL;
	xun *pFreeNode = NULL;
	pzh = pFreeNode = pHead->zhenx;
	while(pzh != pHead)
	{
		if(a == pzh->zhi)
		{
			pzh->zhens->zhenx = pzh->zhenx;
			pzh->zhenx->zhens = pzh->zhens;
			pFreeNode = pzh;
			pzh = pzh->zhenx;
			free(pFreeNode);
			pFreeNode = NULL;
		}
		else
			pzh = pzh->zhenx;
	}
	return 0;
}
int Destorycycle(xun **ppHead)
{
	xun *pTmpNode = NULL;
	xun *pFreeNode = NULL;
	pTmpNode = pFreeNode = (*ppHead)->zhenx;
	while(pTmpNode != *ppHead)
	{
		pFreeNode = pTmpNode;
		pTmpNode = pTmpNode->zhenx;
		free(pFreeNode);
		pFreeNode = NULL;
	}
	free(*ppHead);
		*ppHead = NULL;
	return 0;
}

main.c

#include"lian.h"
int main(void)
{
	xun *year = chuanglian();
	xun *sui = chuanglian();
	
	chalian(year,1);
	chalian(year,0);
	chalian(year,0);
	chalian(year,3);
	chalian(year,5);
	chalian(year,7);
	chalian(year,9);
	chalian(year,0);
	weilian(sui,2);
	weilian(sui,4);
	weilian(sui,6);
	weilian(sui,8);
	weilian(sui,10);
	showlian(year);
	showlian(sui);
	Deletecycle(year,0);
	showlian(year);
	printf("year:%p\n",year);
	printf("sui:%p\n",sui);
	Destorycycle(&year);
	Destorycycle(&sui);
	printf("year:%p\n",year);
	printf("sui:%p\n",sui);
	return 0;
}

lian.h

#ifndef __CIRLIST_H__
#define __CIRLIST_H__

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

typedef int type;
typedef struct xun
{
	type zhi;
	struct xun *zhens;
	struct xun *zhenx;
}xun;
//创建双向循环链表
extern xun *chuanglian(void);
//头插法
extern int chalian(xun *ptou,type a);
//尾插法
extern int weilian(xun *ptou,type a);
//打印链表
extern int showlian(xun *ptou);
//删除值
extern int Deletecycle(xun *pHead,type a);
//销毁链表
extern int Destorycycle(xun **pHead);
#endif

5.数组和链表的区别

  • 数组空间是连续的
  • 链表空间可以是不连续的
  • 数组必须元素有限
  • 链表元素是没有上限的
  • 数组插入和删除效率比较低
  • 链表的插入和删除效率比较高
  • 数组访问元素比较方便
  • 链表访问元素不太方便
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

you-_ling

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值