ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

单链表的查找、插入和删除—不带头结点

2020-11-01 15:03:25  阅读:144  来源: 互联网

标签:结点 单链 int pFirst pos 链表 PNODE 查找


/**********************************************/ 
/***********    不带头结点的方法     **********/ 
/**********************************************/ 

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

/* 定义结构体 */
typedef struct Node
{
	int data;			//数据域
	struct Node * pNext;//指针域
}NODE, * PNODE;         //由于使用了typedef, 所以NODE <=> struct Node  ,  PNODE <=> struct Node * 

/* 函数声明 */
PNODE create_list();					//创建一个链表
void traverse_list(PNODE pFirst);			//遍历整个链表并输出
bool is_empty(PNODE pFirst);				//判断链表是否为空
void search_list(PNODE pFirst, int val);		//链表的查找
bool insert_list(PNODE pFirst, int pos, int value);	//链表的插入
bool delete_list(PNODE pFirst, int pos, int * pval);	//链表的删除
/* 主函数 */
int main()
{
	PNODE pFirst = NULL;  //首指针为空,用来保存首结点的地址
	int val;			 //用来保存删除的元素
	int location;        //保存查找元素的位置 
	
	//1.创建一个链表,并返回首结点的地址给pFirst
	pFirst = create_list(); 
 	//2.遍历整个链表
	traverse_list(pFirst); 
	//3.判断链表是否为空
	if(is_empty(pFirst))	   
	{
		printf("\n链表为空\n");
	}
	else
	{
		printf("\n链表非空\n");
	}
	//4.链表的查找
	int s_val;
	printf("请输入你要查找的元素: ");
	scanf("%d", &s_val);
	search_list(pFirst, s_val);
	//5.链表的插入
	int pos, i_val;
	printf("\n请输入你要插入的位置: ");
	scanf("%d", &pos); 
	printf("请输入你要插入的元素: ");
	scanf("%d", &i_val); 
	insert_list(pFirst, pos, i_val);
	printf("链表插入后");
	traverse_list(pFirst); 
	//6.链表的删除
	printf("\n请输入你要删除的位置: ");
	scanf("%d", &pos); 
	if( delete_list(pFirst, pos, &val) )
	{
		printf("删除成功,您删除的元素是:%d\n", val);
	}
	else
	{
		printf("您删除的元素不存在!\n");
	}
	printf("链表删除后");
	traverse_list(pFirst); 

	return 0;
}
/* 调用函数 */
/*———————————————————————————————————————————————————————*/
PNODE create_list()
{
	int len;      //用来存放有效节点的个数
	int i;
	int temp_val; //临时存放用户输入结点数据域的值

	PNODE pFirst = NULL; 

	PNODE pNew;
	
	printf("请输入您要生成的链表节点的个数: len = ");
	scanf("%d", &len);

	for(i = 0; i<len; i++)
	{
		printf("请输入第%d个节点数据域的值 :", len-i);
		scanf("%d", &temp_val);
		
		//循环一次分配一个存放有效数据的结点
		pNew = (PNODE)malloc(sizeof(NODE));
		if(NULL ==pNew)     {printf("分配失败,程序终止!"); exit(-1);}
		pNew->data = temp_val;
		
		//头插法
		pNew->pNext = pFirst;
		pFirst = pNew;  
	}

	return pFirst;  //返回首结点的地址
}
/*———————————————————————————————————————————————————————*/
void traverse_list(PNODE pFirst)
{
	PNODE p = pFirst;  //首结点的指针域赋给p,即首结点赋给p 【注意区分头结点和首结点】

	printf("链表的数据为:\n");
	while(NULL != p)
	{
		printf("%d ", p->data);
		p = p->pNext;        //下一个结点赋给p
	}

	printf("\n");
}
/*———————————————————————————————————————————————————————*/
bool is_empty(PNODE pFirst)
{
	if(NULL == pFirst->pNext)
	{
		return true;
	}
	else
	{
		return false;
	}
}
/*———————————————————————————————————————————————————————*/
void search_list(PNODE pFirst, int val)
{
	PNODE p = pFirst;      //不带头结点 
	int count = 0;

	//最终版 
	while (NULL != p)       //只要指针域指向的不是空结点就不结束
	{
		count++;
		if (p->data == val)
		{
			printf("找到了!\n%d的位置是: %d\n\n", val, count);
			break; 	  //核心语句 
		}
		p = p->pNext;
	}
	if (NULL == p || p->data != val)
	{
		printf("没找到!\n");
	}
}

/*———————————————————————————————————————————————————————*/
//在pHead所指向链表的第pos个节点的前面插入一个新的结点,假定pos为3
bool insert_list(PNODE pFirst, int pos, int value)
{
	int i = 1;    //缺少头结点,变量i的值加1 
	PNODE p = pFirst;

	while(NULL != p && i<pos-1) //i<3-1=2, 取值为1,循环执行了一次,p指向了第一个有效结点
	{
		p = p->pNext;
		i++;
	}
	if(NULL == p || i>pos-1)
	{
		return false;
	}

	//如果程序能执行到这一行说明p已经指向了第pos-1个结点,但第pos-1个节点是否存在无所谓
	//分配需要插入的结点
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if(NULL == pNew)    {printf("动态分配内存失败!"); exit(-1);}

	pNew->data = value;

	//将新的结点存入p节点的后面【即第pos个节点的前面】,若没明白请回头学习如何插入节点
/*
	第一种插入法 
	PNODE q;
	q = p->pNext;
	p->pNext = pNew;
	pNew->pNext = q;
*/ 
	//第二种插入法 
	pNew->pNext = p->pNext;
	p->pNext = pNew; 

	return true;
}
/*———————————————————————————————————————————————————————*/
//删除第pos个结点,假定pos为3
bool delete_list(PNODE pFirst, int pos, int * pval)
{
	int i = 1;      //缺少头结点,变量i的值加1 
	PNODE p = pFirst;

	while(NULL != p && i<pos-1)//i<3-1=2, 取值为1,循环执行了一次,p指向了第一个有效结点
	{
		p = p->pNext;
		i++;
	}
	if(NULL == p && i>pos-1)
	{
		return false;
	}

	//如果程序能执行到这一行说明p已经指向了第pos-1个结点,并且第pos个节点是存在的
	//这里的指向解释一下:通俗的说就是等于这个结点的意思
	
	PNODE q = p->pNext; //q指向待删除的结点

	*pval = q->data;    //返回删除的值

	//删除p节点后面的结点,若没明白请回头学习如何删除节点
	p->pNext = p->pNext->pNext;
	free(q);			//释放q所指向的节点所占的内存
	q = NULL;			//q = p->pNext = NULL,表示p指针域指向的结点已被删除
	
	return true;
}
/*———————————————————————————————————————————————————————*/

标签:结点,单链,int,pFirst,pos,链表,PNODE,查找
来源: https://www.cnblogs.com/gmengshuai/p/13909509.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有