单链表创建,取值,查找,插入,删除的实验笔记1(计算机软件基础)

一、实验目的和要求
目的:

  • 熟悉单链表的创建,取值,查找,插入,删除等操作。

要求:

  1. 初始化单链表La
  2. 在La中插入一个新结点
  3. 删除La中某个结点

二、实验内容
(1)单链表中插入结点
插入结点有两种方法,一种头插,一种尾插
头插法:从空表开始,重复读入数据,生成新结点,将读入的数据存放到新结点的数据域中,然后将新结点插入到当前链表的头结点之后,直至读入结束标志为止,头插法创建链表的根本在于最后两条语句:

node->next = head->next;
//将头指针所指向的下一个结点的地址,赋给新创建结点的next
head->next= node;
//将新创建的结点的地址赋给头指针的下一个结点

在这里插入图片描述
尾插法:将新结点插到当前单链表的表尾处

end->next = node;
//将新开辟的node的地址赋给head的下一个结点地址
end = node;
//将新建的结点node的地址赋给尾结点end

(2)单链表中删除结点

ListDelete (&L, i, &e):删除单链表L的第i个结点,将结点元素值赋给e。

利用循环操作将p指针定位到第i-1个元素位置,用q指针指向第i个结点 位置并将元素值赋给e,让第i-1个元素的指针域指向第i+1个元素,然后 释放q结点;单链表的删除标准语句序列为:

  1. q = p->next;
  2. p->next = q->next;
  3. e = q->data;

三、依据的基本原理
整个程序的流程看主函数,具体函数实现过程请看第四点,为方便讲解,我直接在代码后通过注释的方式讲解原理:

int main(int argc, int argv[])  #定义主函数
{
	int opt = 0; #定义变量opt
	int num = 0; #定义变量num
	//创建链表
	printf("请创建一个链表:\n");
	pNode phead = create_list(); #运行自定义的创建链表函数
	//打印输出链表
	printf("打印输出链表:\n");
	traverse_list(phead); #运行自定义的输出链表函数
	
	//在数字key前边插入数字data
	int key; #定义变量key
	int data; #定义变量data
	Node node;
	printf("在数字几前插入:\n");
	scanf("%d",&data); #输入
	printf("输入你想要插入的数字:\n");
	scanf("%d",&key); #输入想插入的数字
	insertnode_bypre(phead,node,key,data); #运行自定义的插入函数
	traverse_list(phead);  #运行自定义的输出链表函数
	
	//在数字key1后边插入数字data1
	int key1;
	int data1; #定义变量
	Node node1;
	printf("在数字几后插入:\n");
	scanf("%d",&data1);
	printf("输入你想要插入的数字:\n");
	scanf("%d",&key1);
	insertnode_byback(phead,node,key1,data1); #后插法
	traverse_list(phead); #运行自定义的输出链表函数
	
	//删除节点
	int deldata;
	printf("删除数字:\n");
	scanf("%d",&deldata);
	deletenode(phead, deldata); #运行自定义的删除结点函数
	traverse_list(phead); #运行自定义的输出链表函数
	
	//查找数字,输出位置
	printf("输入想要查找的数字:\n");
	scanf("%d",&num);
	searchnode(phead,num); #运行自定义的按值查找函数
	return 0;
}

总的来说,该程序先创建一个链表,用户可根据需要选择创建的链表长度,并给链表赋值,创建成功后,输出链表.

然后分别使用前插法与后插法插入数据随后删除数据.

最后查找某个数据所在的位置.至此,程序结束.

四、实验步骤
这是一个用结构体写的程序,拆开,会很好理解.

程序一开始,就用结构体定义结点,把struct Node *定义为新类型pNode,是一个结构体的指针。随后,自定义了7个函数,分别是初始化一个链表结点, 创建链表函数, 遍历链表, 按值查找操作, 前插法, 后插法, 删除结点.

为了便于读者理解,我还是通过注释的方式进行讲解:

//(1)初始化一个链表结点
pNode init_node(Node *pnode, int data)
{
	pnode = (Node *)malloc(sizeof(Node));
	pnode -> data = data;//初始化数字域
	pnode -> next = NULL;//初始化指针域
	return pnode;
}
//创建链表函数
pNode create_list()
{
	int i;  //    用于下面循环
	int len;  //    用来存放有效节点的字数
	int val;  //    用于临时存放用户输入的数据
	pNode pHead = (pNode)malloc(sizeof(Node)); // 分配一个不存放有效数据的头结点
	pNode pTail = pHead;   //链表的最后一个节点
	pTail->next = NULL;   //    最后一个节点的指针置为空
	printf("请输入节点个数:");
	scanf("%d", &len);
	for (i = 0; i < len; i++)
	{
		printf("第 %d 个节点的数值:", i + 1);
		scanf("%d", &val);
		pNode pNew = (pNode)malloc(sizeof(Node));    //为节点分配空间	
		//将用户输入的数据赋给节点的成员,将最后一个节点的指针指向
		//下一个新的节点,将新节点中的指针置为空,将新节点赋给最后的一个节点
		pNew -> data = val;   //将用户输入的数据赋给节点的成员
		pTail -> next = pNew; //将最后一个节点的指针指向下一个新的节点
		pNew -> next = NULL; //将新节点中的指针置为空
		pTail = pNew;  //将新节点赋给最后的一个节点
		printf("successful!");	
	}
	return pHead; //返回头节点
}
//(2)在链表中插入一个新结点。
//前插法
pNode insertnode_bypre(Node *phead, Node node,int data,int key)
{
	Node *pnode = init_node(&node, data);//初始化插入的结点
	Node *ptmp = phead;
	
	if (phead == NULL)//链表为空,直接返回初始化的值
	{
		return pnode;
	}
	else if (phead->data == key)//处理的第一个结点是否为目标结点
	{
		phead = pnode;
		pnode->next = ptmp;
	}
	else
	{
		while((ptmp->next != NULL) && (ptmp->next->data != key))
		{
			ptmp = ptmp->next;
		}
		if (ptmp->next == NULL)//没有找到的情况
		{
			printf("insert key NOT FOUND\n");
		}
		else//把新结点插入到目标结点的前面
		{
			ptmp = (Node *)malloc(sizeof(Node));  //分配一个Node类型大小的内存空间,并把分配空间的首地址强制转换成Node *类型的
			ptmp->data = data;  //  为新结点的数据域赋值
            ptmp->next = phead->next; //  将头指针所指向的下一个结点的地址,赋给新创建结点的next 
            phead->next = ptmp; //  将新创建的结点的地址赋给头指针的下一个结点
		}
	}
	printf("successful!");
	return phead;
}
//后插法
pNode insertnode_byback(Node *phead,Node node ,int data,int key)
{
	Node *pnode = init_node(&node, data);//初始化插入的结点
	Node *ptmp = searchnode(phead,key);//查找目标结点
	
	if (ptmp == NULL)//链表为空,或者没有找到
	{
		printf("Link is empty or not found key!\n");
		return phead;
	}
	if (ptmp->next == NULL)//如果key为最后一个结点
	{
		ptmp->next = pnode;
	}
	else//将新结点插入到目标结点的后面
	{
		ptmp = (Node *)malloc(sizeof(Node)); //分配一个Node类型大小的内存空间,并把分配空间的首地址强制转换成Node *类型的
		ptmp -> next = NULL;  //  初始化头结点指向的下一个地址为 NULL
		phead -> next = ptmp;
		phead = phead->next;
	}
	printf("successful!");
	return phead;
}
// (3)删除链表中的某一个结点。
pNode deletenode(Node *phead, int key)
{
	Node *ptmp = phead;
	Node *tmp = NULL;
	
	if (phead == NULL)//处理链表为空的情况
	{
		printf("Link is empty,delete fail!\n");
		return NULL;
	}
	else if(phead->data == key)//单独处理第一个结点
	{
		phead = phead->next;
		free(ptmp); //释放目标结点
		ptmp = NULL;
	}
	else
	{
		while (ptmp->next != NULL && ptmp->next->data != key)//没找&&没有找到
		{
			ptmp = ptmp->next;
		}
		if (ptmp->next == NULL)//没有找到
		{
			printf("delete key is not found!\n");
			return phead;
		}
		if (ptmp->next->data == key)//找到目标结点并删除
		{
			tmp = ptmp->next;
            ptmp->next = tmp->next;
			free(tmp); //释放目标结点
			tmp = NULL; 
		}
	}
	printf("successful!");
	return phead;
}
// (4)在链表中查找某结点并返回其位置。
pNode searchnode(Node *phead,int key)
{
	Node *ptmp = phead;
	int i = 0;
	if (ptmp == NULL) //查找结点,判断该结点是否存在
	{
		return NULL;
	}
	
	while (ptmp->data != key && ptmp->next != NULL)
	{	
		i=i+1;
		ptmp = ptmp->next;
	}
	
	if (ptmp -> data == key)
	{	
		printf("所在位置为:%d\n",i);
		return 0;
	}
	if (ptmp->next == NULL)
	{
		printf("该数字不在链表中\n");
		return NULL;
	}
}
//(5)打印输出链表中的结点元素值。
void traverse_list(pNode pHead)
{
	pNode p = pHead->next;   //将头节点的指针给予临时节点p
	while (NULL != p)  //节点p不为空,循环
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

五、实验结果及分析
在这里插入图片描述
六、附录(程序源码)

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

typedef struct node{ //用结构体定义结点
	int data;
	struct node *next;
}Node, *pNode; //把struct Node *定义为新类型pNode,是一个结构体的指针。  

//初始化一个链表结点
pNode init_node(Node *pnode, int data);
//创建链表函数
pNode create_list();
//遍历链表
void traverse_list(pNode pHead);
//按值查找操作
pNode searchnode(Node *phead, int key);
//前插法
pNode insertnode_bypre(Node *phead, Node node, int data, int key);
//后插法
pNode insertnode_byback(Node *phead, Node node, int data, int key);
//删除结点
pNode deletenode(Node *phead, int key);


//(1)初始化一个链表结点
pNode init_node(Node *pnode, int data)
{
	pnode = (Node *)malloc(sizeof(Node));
	pnode -> data = data;//初始化数字域
	pnode -> next = NULL;//初始化指针域
	
	return pnode;
}

//创建链表函数
pNode create_list()
{
	int i;  //    用于下面循环
	int len;  //    用来存放有效节点的字数
	int val;  //    用于临时存放用户输入的数据
	pNode pHead = (pNode)malloc(sizeof(Node)); // 分配一个不存放有效数据的头结点
	pNode pTail = pHead;   //链表的最后一个节点
	pTail->next = NULL;   //    最后一个节点的指针置为空
	printf("请输入节点个数:");
	scanf("%d", &len);
	for (i = 0; i < len; i++)
	{
		printf("第 %d 个节点的数值:", i + 1);
		scanf("%d", &val);
		pNode pNew = (pNode)malloc(sizeof(Node));    //为节点分配空间
		
		//补充代码,将用户输入的数据赋给节点的成员,将最后一个节点的指针指向
		//下一个新的节点,将新节点中的指针置为空,将新节点赋给最后的一个节点
		pNew -> data = val;   //将用户输入的数据赋给节点的成员
		pTail -> next = pNew; //将最后一个节点的指针指向下一个新的节点
		pNew -> next = NULL; //将新节点中的指针置为空
		pTail = pNew;  //将新节点赋给最后的一个节点
		printf("successful!");	
	}
	return pHead; //返回头节点
	
}

//(2)在链表中插入一个新结点。
//前插法
pNode insertnode_bypre(Node *phead, Node node,int data,int key)
{
	Node *pnode = init_node(&node, data);//初始化插入的结点
	Node *ptmp = phead;
	
	if (phead == NULL)//链表为空,直接返回初始化的值
	{
		return pnode;
	}
	else if (phead->data == key)//处理的第一个结点是否为目标结点
	{
		phead = pnode;
		pnode->next = ptmp;
	}
	else
	{
		while((ptmp->next != NULL) && (ptmp->next->data != key))
		{
			ptmp = ptmp->next;
		}
		if (ptmp->next == NULL)//没有找到的情况
		{
			printf("insert key NOT FOUND\n");
		}
		else//把新结点插入到目标结点的前面
		{
			ptmp = (Node *)malloc(sizeof(Node));  //分配一个Node类型大小的内存空间,并把分配空间的首地址强制转换成Node *类型的
			ptmp->data = data;  //  为新结点的数据域赋值
            ptmp->next = phead->next; //  将头指针所指向的下一个结点的地址,赋给新创建结点的next 
            phead->next = ptmp; //  将新创建的结点的地址赋给头指针的下一个结点
		}
	}
	printf("successful!");
	return phead;
}

//后插法
pNode insertnode_byback(Node *phead,Node node ,int data,int key)
{
	Node *pnode = init_node(&node, data);//初始化插入的结点
	Node *ptmp = searchnode(phead,key);//查找目标结点
	
	if (ptmp == NULL)//链表为空,或者没有找到
	{
		printf("Link is empty or not found key!\n");
		return phead;
	}
	if (ptmp->next == NULL)//如果key为最后一个结点
	{
		ptmp->next = pnode;
	}
	else//将新结点插入到目标结点的后面
	{
		ptmp = (Node *)malloc(sizeof(Node)); //分配一个Node类型大小的内存空间,并把分配空间的首地址强制转换成Node *类型的
		ptmp -> next = NULL;  //  初始化头结点指向的下一个地址为 NULL
		phead -> next = ptmp;
		phead = phead->next;
	}
	printf("successful!");
	return phead;
}

// (3)删除链表中的某一个结点。
pNode deletenode(Node *phead, int key)
{
	Node *ptmp = phead;
	Node *tmp = NULL;
	
	if (phead == NULL)//处理链表为空的情况
	{
		printf("Link is empty,delete fail!\n");
		return NULL;
	}
	else if(phead->data == key)//单独处理第一个结点
	{
		phead = phead->next;
		free(ptmp); //释放目标结点
		ptmp = NULL;
	}
	else
	{
		while (ptmp->next != NULL && ptmp->next->data != key)//没找&&没有找到
		{
			ptmp = ptmp->next;
		}
		if (ptmp->next == NULL)//没有找到
		{
			printf("delete key is not found!\n");
			return phead;
		}
		if (ptmp->next->data == key)//找到目标结点并删除
		{
			tmp = ptmp->next;
            ptmp->next = tmp->next;
			free(tmp); //释放目标结点
			tmp = NULL; 
		}
	}
	printf("successful!");
	return phead;
}


// (4)在链表中查找某结点并返回其位置。
pNode searchnode(Node *phead,int key)
{
	Node *ptmp = phead;
	int i = 0;
	if (ptmp == NULL) //查找结点,判断该结点是否存在
	{
		return NULL;
	}
	
	while (ptmp->data != key && ptmp->next != NULL)
	{	
		i=i+1;
		ptmp = ptmp->next;
	}
	
	if (ptmp -> data == key)
	{	
		printf("所在位置为:%d\n",i);
		return 0;
	}
	if (ptmp->next == NULL)
	{
		printf("该数字不在链表中\n");
		return NULL;
	}
}

//(5)打印输出链表中的结点元素值。
void traverse_list(pNode pHead)
{
	pNode p = pHead->next;   //将头节点的指针给予临时节点p
	while (NULL != p)  //节点p不为空,循环
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}


//主函数
int main(int argc, int argv[])
{
	int opt = 0;
	int num = 0;
	//创建链表
	printf("请创建一个链表:\n");
	pNode phead = create_list();
	//打印输出链表
	printf("打印输出链表:\n");
	traverse_list(phead);
	
	//在数字key前边插入数字data
	int key;
	int data;
	Node node;
	printf("在数字几前插入:\n");
	scanf("%d",&data);
	printf("输入你想要插入的数字:\n");
	scanf("%d",&key);
	insertnode_bypre(phead,node,key,data);
	traverse_list(phead);
	
	//在数字key1后边插入数字data1
	int key1;
	int data1;
	Node node1;
	printf("在数字几后插入:\n");
	scanf("%d",&data1);
	printf("输入你想要插入的数字:\n");
	scanf("%d",&key1);
	insertnode_byback(phead,node,key1,data1);
	traverse_list(phead);
	
	//删除节点
	int deldata;
	printf("删除数字:\n");
	scanf("%d",&deldata);
	deletenode(phead, deldata);
	traverse_list(phead);
	
	//查找数字,输出位置
	printf("输入想要查找的数字:\n");
	scanf("%d",&num);
	searchnode(phead,num);
	return 0;
}

以上就是全部内容,如果大家有更好的方法,欢迎大家与我讨论
在这里插入图片描述

发布了32 篇原创文章 · 获赞 63 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zbp_12138/article/details/102888582