014.2021-07-08(3)

这篇博客介绍了如何使用C语言实现链表的基本操作,包括创建空链表、在头部插入元素、在尾部插入元素、有序插入元素、打印链表内容、清除链表、销毁链表以及删除指定元素。通过示例展示了如何动态分配内存并管理链表节点,适用于数据结构学习和C语言编程实践。
摘要由CSDN通过智能技术生成
#include<stdio.h>
#include <stdlib.h>

#include"linkedList.h"


List * create()
{
	List * l = (List *)malloc(sizeof(List));

	l->first = NULL;
	l->last =NULL;
	l->n = 0;

	return l;
}


void    headInsert(List * l,ElemType x)
{
	//为新节点分配空间
	lNode * p = (lNode *)malloc(sizeof(lNode));
	//lNode node;

	//为p节点赋值
	p->data = x;
	p->next = NULL;


	//把新节点插入到链表中
	if(l->first == NULL) // l->n == 0
	{
		l->first = p;
		l->last = p;
	}
	else
	{
		p->next = l->first;
		l->first = p;
	}

	l->n++;

	//思考:需要返回值吗???

}



/*
	功能:往链表尾部位置插入一个元素(尾插法)
*/
void tailInsert(List * l,ElemType x)
{
	//为新节点分配空间
	lNode * p = (lNode *)malloc(sizeof(lNode));
	//lNode node;

	//为p节点赋值
	p->data = x;
	p->next = NULL;


	//把新节点插入到链表中(尾插法)
	if(l->first == NULL)//当前链表为空,p节点是第一个节点
	{
		l->first = l->last = p;
	}
	else
	{
		l->last->next = p;
		l->last = p;
	}

	l->n++;
	
}

/*
	功能:在一个有序(以升序为例)的链表中插入一个元素使之仍然有序

*/
void insert(List * l,ElemType x)
{
	
	//为新节点分配空间
	lNode * p = (lNode *)malloc(sizeof(lNode));
	//lNode node;

	//为p节点赋值
	p->data = x;
	p->next = NULL;

	if(l->n == 0)
	{
		l->last = l->first = p;
		l->n ++;
		return ;
	}
	
	//进行插入。第一步找到插入的位置,找到第一个比x大的节点 q

	lNode * q = l->first;
	lNode * r = NULL;
	while(q)
	{
		if(q->data > x)
		{
			break;//找到了就跳出循环
		}
		r = q;//r保存了q的前驱节点地址
		q = q->next;//没找到就继续往后找,直到 q为NULL
	}

	//分情况讨论
	if(q == l->first)//第一个元素比x就大。p节点就要头插
	{
		p->next = l->first;
		l->first = p;
	}
	else if(q == NULL)//没有比我大的。尾插
	{
		l->last->next = p;
		l->last = p;
	}
	else//插入到中间
	{
		r->next = p;
		p->next = q;
	}

	l->n ++;
}


void printfLkList(List * l)
{

	lNode * p = l->first;

	while(p)//for(i=0;i<l->n;i++)
	{
		printf("%d ",*(int *)(p->data));
		p = p->next;
	}
	printf("\n");

}

void printfLkList1(List * l)
{

	lNode * p = l->first;

	while(p)//for(i=0;i<l->n;i++)
	{
		printf("%lf ",*(double *)(p->data));
		p = p->next;
	}
	printf("\n");

}



void clearLkList(List * l)
{
	
	lNode *p = l->first;
	
	while(p)
	{
		//先保存下一个节点
		l->first = p->next;

		//删除当前节点
		free(p->data);
		p->next = NULL;//释放一个节点之前,务必把指针域清空
		free(p);

		//让p指向新的first
		p = l->first;
	}

	l->first = l->last = NULL;
	l->n = 0;
}


void destroyLkList(List * l)
{
	
	lNode *p = l->first;
	
	while(p)
	{
		//先保存下一个节点
		l->first = p->next;

		//删除当前节点
		free(p->data);
		p->next = NULL;//释放一个节点之前,务必把指针域清空
		free(p);

		//让p指向新的first
		p = l->first;
	}

	l->first = l->last = NULL;
	l->n = 0;

	free(l);
}


void delete(List * l,ElemType x)
{
	//1,找到该节点
	lNode * p = l->first;
	lNode * r = NULL;
	while(p)
	{
		if(p->data == x)//p就是要删除的节点
		{
			break;
		}
		r = p;//让r保存 p的前驱节点
		p = p->next;
	}

	//2,根据实际情况进行删除操作
	if(p == NULL)//没有找到要删除的节点
	{
		return ;	
	}
	else//找到了要删除的节点
	{
		//分情况
		if(p == l->first)//要删除的节点是第一个节点
		{
			l->first = l->first->next;
			p->next = NULL;
			free(p);
		}
		else if(p->next == NULL)//要删除的节点是最后一个节点
		{
			//不能直接 free(p);因为,倒数第二个节点的指针域还没有清空
			r->next = NULL;
			//p->next = NULL;
			free(p);
			l->last = r;
		}
		else//删除中间的节点
		{
			r->next = p->next;
			p->next = NULL;
			free(p);
		}

		l->n --;
	}
}


int find(List * l,ElemType x)
{
	lNode * p = l->first;
	while(p)
	{
		if(p->data == x)
		{
			return 1;
		}
		p = p->next;
	}
	return 0;
}


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

#include"linkedList.h"
void test01()
{
	List * l = create();

	int * p;
	
	p = (int *)malloc(sizeof(int));
	*p = 10;
	headInsert(l,(void *)p);
	
	p = (int *)malloc(sizeof(int));
	*p = 60;
	headInsert(l,(void *)p);


	p = (int *)malloc(sizeof(int));
	*p = 80;
	headInsert(l,(void *)p);
	

	p = (int *)malloc(sizeof(int));
	*p = 50;
	headInsert(l,(void *)p);
	printfLkList(l);

	//destroyLkList(l);
}


void test02()
{
	List * l = create();

	double * p;
	
	p = (double *)malloc(sizeof(double));
	*p = 1.1;
	headInsert(l,(void *)p);
	
	p = (double *)malloc(sizeof(double));
	*p = 2.3;
	headInsert(l,(void *)p);


	p = (double *)malloc(sizeof(double));
	*p = 4.5;
	headInsert(l,(void *)p);
	

	p = (double *)malloc(sizeof(double));
	*p = 8.8;
	headInsert(l,(void *)p);
	printfLkList1(l);

	//destroyLkList(l);
}

int main()
{

	test01();
	test02();
	return 0;

}






#ifndef __LINKEDLIST_H__
#define __LINKEDLIST_H__

typedef     void * ElemType;
//假设有如下需求:需要创建两个链表,并且两个链表的元素的数据类型不一样
//比如一个是 Int 一个是 double
//那么 ElemType 就不能是普通的类型
//我们得找到不同类型数据的共同点:不管什么类型都需要有内存来保存-》都会有一个地址
// 而不同类型的地址都可以和 void * 相互转换
//所以链表的数据域可以定为 void * -》也就是说我们在链表中只保存数据的 地址
	

					
struct linkedListNode
{
	ElemType data;//数据域 用来保存数据
	struct linkedListNode *next;//存储下一个元素的地址 ,指针域
};

typedef struct linkedListNode lNode;	

struct linkedList//头结点
{
		lNode* first;//用来保存链表中第一个节点的地址
		lNode* last;//用来保存链表中最后一个节点的地址
		int n;//用来保存链表节点的个数
};//头结点
	
typedef struct linkedList List;



/*
	功能:创建一个空链表
	
	返回值:
		返回空链表的头结点指针
*/
List * create();


void    headInsert(List * l,ElemType x);

void tailInsert(List * l,ElemType x);


void insert(List * l,ElemType x);

void printfLkList(List * l);


void clearLkList(List * l);


void destroyLkList(List * l);


void delete(List * l,ElemType x);


int find(List * l,ElemType x);

void printfLkList1(List * l);


#endif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值