学链表有感

链表的定义

链表的定义:

  1. 在内存上不连续存储(离散的)。
  2. 通过指针相连接。
  3. 每个节点前后都连接了一个节点(前面只有一个,后面只有一个)。

总结:

n个节点连续分配,彼此之间通过指针相连接,每个节点都只有一个前驱、后继,首节点没有前驱节点,尾节点没有后续节点。

专业术语:

首节点:第一个有效节点

尾节点:最后一个有效节点

头节点:第一个有效节点之前的节点,头节点并不存放有效数据,加头结点的目的是为了方便对链表的操作;头节点的数据类型和首节点数据类型一致

头指针:指向头节点的指针变量(不是指向首节点)

尾指针:指向尾节点的指针变量

如果希望通过调用一个函数来对链表进行操作,我们最起码需要哪些参数:

只需要一个参数,即头指针,因为我们可以通过头指针找到头结点的地址,只要能够找到头节点就可以找到整个链表的其它所有信息(可以理解为发现了老鼠尾巴就能抓到整只老鼠)。

如图所示

线性链表图 

链表的分类

单链表、双链表、循环链表、非循环链表

双链表:每一个节点有两个指针域

循环链表:能通过任何一个节点找到其他节点(类似于蛇咬自己的尾巴,尾节点的指针域返回指向首节点)

算法:遍历、查找、清空、销毁、求长度、排序、删除节点、插入节点

头文件

#ifndef _LB_H_
#define _LB_H_
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct Node
{
	int data;
	struct Node *pNext;
}Node,*PNode;

PNode create_Node();
void traversal_Node(PNode amns);
bool empty_Node(PNode Node);
void length_Node(PNode Node,int *val);
void sort_Node(PNode Node,int len);
void insert_Node(PNode Node ,int pos,int val);
void delete_Node(PNode Node,int pos,int *);
#endif

函数实现

#include"lb.h"

PNode create_Node()
{
	//创建单链表
	int len=0;
	int val=0;
	printf("请输入索要创建的链表个数len= ");
	scanf("%d",&len);
	PNode Phead=(PNode)malloc(sizeof(Node));
	//创建头节点
	PNode Pt=Phead;
	//创建交换指针
	Pt->pNext=NULL;
	int i=0;
	for(i=0;i<len;i++)
	{
		printf("请输入所要赋的值val= ");
		scanf("%d",&val);
		PNode Pnew=(PNode)malloc(sizeof(Node));
		//创建动态空间用于存储
		if(NULL==Pnew)
		//判断空间是否创建成功
		{
			printf("链表创建失败!");
		}
		Pnew->data=val;
		//将输入的值赋给数据域
		Pt->pNext=Pnew;
		//使头节点的指针域指向创建的空间
		Pt=Pnew;
		//使交换指针指向创建的空间
		Pt->pNext=NULL;
		//使新指向节点的指针域为空(尾指针为空)
	}
	return Phead;
	//将头节点的地址返回
}
void traversal_Node(PNode amns)
	//遍历链表
{
	PNode p=amns->pNext;
	//创建结构体指针指向首节点
	while(NULL!=p)
	//判断指针指向的下一节点是否为空
	{
		printf("%d ",p->data);
		p=p->pNext;
	}
	return;
}

bool empty_Node(PNode Node)
	//判断头节点是否为空
{
	if(NULL==Node->pNext)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void length_Node(PNode Node,int *val)
	//计算链表的长度,将长度返回给*val
{
	int cnt=0;
	//cnt为计数器
	PNode p=Node->pNext;
	//创建结构体指针指向首节点
	while(NULL!=p)
	{
		p=p->pNext;
		cnt++;
	}
	*val=cnt;
	return;
}

void sort_Node(PNode Node,int len)
	//链表排序
{	
	int i=0;
	int j=0;
	int t=0;
	//创建循环运行条件及交换变量
	PNode a,b;
	//创建结构体指针用来指向节点判断数据域值的大小
	for(i=0,a=Node->pNext;i<len-1;i++,a=a->pNext)
		//思想与数组的排序别无二致,在清楚之前要多想!要多思考!
	{
		for(j=i+1,b=a->pNext;j<len;j++,b=b->pNext)
		{
			if(a->data>b->data)
			{
				t=a->data;
				a->data=b->data;
				b->data=t;
			}
		}
	}
	return;
}

void insert_Node(PNode Nod,int pos,int val)
{
	//在pos前插入一个节点,即新节点替代老节点的位置,老节点后移
	int i=0;
	PNode p=Nod;
	//起始位i为0,创建结构体指针指向头节点
	while(NULL!=p&&i<pos-1)
	//对p指针进行判断,当p指向NULL(尾节点的值或链表为空时)停止
	//当i不满足条件时停止
	{
		p=p->pNext;
		i++;
	}
	if(i>pos-1||p==NULL)
	//判断循环结束时的指针和起始位是由什么原因导致结束的
	//如果是因为链表条件不满足参数则执行return
	{
		return;
	}
	//若条件满足则执行插入节点操作
	PNode Pnew=(PNode)malloc(sizeof(Node));
	//申请动态空间创建新节点
	Pnew->pNext=p->pNext;
	p->pNext=Pnew;
	Pnew->data=val;
	//赋值给新节点
	return;
}
void delete_Node(PNode Node,int pos,int *val)
	//删除指定位置的节点,操作和插入操作逻辑类似
{
	int i=0;
	PNode p=Node;
	while(NULL!=p&&i<pos-1)
	{
		p=p->pNext;
		i++;
	}
	if(i>pos-1||NULL==p)
	{
		printf("所要删除的节点不存在!");
		return;
	}
	PNode Pnew=p->pNext;
	//创建结构体指针指向所要删除的节点
	*val=Pnew->data;
	//将所要删除的值赋给变量
	p->pNext=Pnew->pNext;
	free(Pnew);
	Pnew=NULL;
	return;
}

主函数

#include"lb.h"

int main(int argc, const char *argv[])
{
	PNode first=NULL;
	first=create_Node();
	traversal_Node(first);
	printf("\n");
	if(empty_Node(first))
	{
		printf("链表为空!\n");
	}
	else
	{
		printf("链表不为空!\n");
	}
	int val=0;
	length_Node(first,&val);
	printf("链表的长度为%d\n",val);
	sort_Node(first,val);
	insert_Node(first,1,367);
	traversal_Node(first);
	delete_Node(first,1,&val);
	printf("\n删除的元素为%d\n",val);
	traversal_Node(first);
	printf("\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值