数据结构单链表基本操作

1.定义

在这里插入图片描述
相比较于顺序表,单链表在内存中存储数据时是不连续的,可以说是一种见缝插针的方式。因为存储时是不连续存储,因此在每一个节点都需要一个指向下一个节点的指针,如此才能把每一个节点串起来,形成一个链表。

2.基本操作

1.初始化链表
2.创建链表(头插法或尾插法)
3.插入节点(前插法或后插法)
4.删除节点
5.查找节点(按序号查找或按值查找)
6.遍历链表
7.释放链表

3.Show Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable:4996) //用于屏蔽4996的错误
#define ElemType int
typedef struct LinkList
{
	ElemType data; //数据
	struct LinkList *next; //指向下一个节点的指针
	
}LinkList;

LinkList *L = NULL; //用L作为全局变量,在下面的函数中就不用再传参
//初始化链表
void InitList()
{
	//L = new LinkList;//分配内存
	L = (LinkList *)malloc(sizeof(LinkList));//分配内存
	L->next = NULL;
	printf("初始化成功!\n");
}
//头插法创建链表
void CreateList_Head()
{
	LinkList *node;
	ElemType data;
	int i = 1;
	printf("第%d个数据:", i);
	scanf("%d", &data);
	while (data != 999) //输入999完成链表创建
	{
		node = (LinkList *)malloc(sizeof(LinkList));
		node->data = data;
		node->next = L->next;
		L->next = node;
		i++;
		printf("第%d个数据:", i);
		scanf("%d", &data);
	}
	printf("创建完成\n");
}
//尾插法创建链表
void CreateList_Tail()
{
	LinkList *p ,*tail;
	tail = L;
	ElemType data;
	ElemType i = 1;
	printf("第%d个数据:", i);
	scanf("%d", &data);
	while (data != 999)
	{
		p = (LinkList *)malloc(sizeof(LinkList));
		p->data = data;
		p->next = NULL;
		tail->next = p;
		tail = p;
		i++;
		printf("第%d个数据:", i);
		scanf("%d", &data);
	}
	printf("创建完成\n");
}
//插入新结点--前插法
void ListInsert_Pre()
{
	LinkList *p = L;
	LinkList *newNode; //要插入的新节点
	ElemType pos,elem;
	printf("请输入要插入的位置:");
	scanf("%d", &pos);
	printf("请输入要插入的数据:");
	scanf("%d", &elem);
	//为新节点分配空间
	//newLinkList = new LinkList;
	newNode = (LinkList *)malloc(sizeof(LinkList));
	newNode->data = elem;
	//判断插入位置是否合法
	if (pos == 0)
		return;
	//寻找pos-1的位置
	ElemType j = 0;
	while (p && j < pos - 1)
	{
		p = p->next;
		j++;
	}
	if (!p || j > pos - 1)
		return;
	newNode->next = p->next;
	p->next = newNode;
}
//插入节点-后插法
void ListInsert_back()
{
	LinkList *p = L;
	LinkList *newNode;
	ElemType pos, elem;
	printf("请输入要插入的位置:");
	scanf("%d", &pos);
	printf("请输入要插入的数据:");
	scanf("%d", &elem);
	//为新节点分配空间
	newNode = (LinkList *)malloc(sizeof(LinkList));
	newNode->data = elem;
	//寻找第pos个节点
	ElemType j = 0;
	while (p && j < pos)
	{
		p = p->next;
		j++;
	}
	if (!p || j > pos)
		return;
	newNode->next = p->next;
	p->next = newNode;
}
//删除某个结点
void ListDel()
{
	LinkList *p = L;
	LinkList *q;//用于记录被删除的节点
	ElemType pos;
	ElemType elem;
	printf("请输入要删除的位置:");
	scanf("%d", &pos);
	//寻找第pos-1个结点
	ElemType j = 0;
	while (p && j < pos - 1)
	{
		p = p->next;
		j++;
	}
	if (!p || j > pos - 1)
		return;
	q = p->next;
	elem = q->data;
	p->next = q->next;
	q->next = NULL;
	printf("被删除的元素为:%d\n", elem);
	free(q);

}
//遍历链表并输出表中元素
void ListTraverse()
{
	if (L == NULL)
	{
		printf("链表为空!\n");
		return;
	}
	LinkList *p;
	p = L->next;
	printf("表中元素:\n");
	while (p)
	{
		printf("%d\t", p->data);
		p = p->next;
	}
	printf("\n");
}
//查找--按值查找
void ListSearch_Value()
{
	LinkList *p;
	p = L->next;
	ElemType elem;
	printf("请出入要查找的值:");
	scanf("%d", &elem);
	ElemType j = 1;
	while (p && p->data != elem)
	{
		p = p->next;
		j++;
	}
	if (!p)
		printf("链表中没有该元素!\n");
	else
		printf("该元素在链表中的位置为:%d\n", j);

}
//查找--按序号查找
void ListSearch_Num()
{
	LinkList *p;
	p = L->next;
	ElemType pos;
	printf("请出入要查找的序号:");
	scanf("%d", &pos);
	ElemType j = 1;
	while (p && j < pos)
	{
		p = p->next;
		j++;
	}
	if (!p || j > pos)
	{
		printf("链表中没有该元素!\n");
		return;
	}
		
	else
		printf("链表中第%d个元素为:%d\n",pos,  p->data);

}
void ListDestroy()
{
	LinkList *p = L;
	LinkList *q = NULL;
	while (p)
	{
		q = p; //保存当前结点
		p = p->next;//让当前结点指向下一个结点
		free(q); //释放当前结点
	}
	free(p);
	L = NULL;
	if (L = NULL)
		printf("释放成功!\n");
	
}
void Menu()
{
	printf("\t\t\t\t***************************************************\n");
	printf("\t\t\t\t1.初始化\t\t\t\t2.创建链表\n");
	printf("\t\t\t\t3.插入节点\t\t\t\t4.删除节点\n");
	printf("\t\t\t\t5.查找节点\t\t\t\t6.遍历链表\n");
	printf("\t\t\t\t7.释放链表\n");
	printf("\t\t\t\t***************************************************\n");
}
//主函数测试
int main()
{
	
	while (1)
	{
		Menu();
		ElemType choice;
		printf("请选择菜单:");
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
		{
			InitList();
			break;
		}
		case 2:
		{
			printf("请选择创建方式(1.头插法  2.尾插法):");
			ElemType num;
			scanf("%d", &num);
			if (num == 1)
			{
				CreateList_Head();
				break;
			}
			if (num == 2)
			{
				CreateList_Tail();
				break;
			}
		}
		case 3:
		{
			printf("请选择插入方式(1.前插法  2.尾插法):");
			ElemType num;
			scanf("%d", &num);
			if (num == 1)
			{
				ListInsert_Pre();
				break;
			}
			if (num == 2)
			{
				ListInsert_back();
				break;
			}
		}
		case 4:
		{
			ListDel();
			break;
		}
		case 5:
		{
			printf("请出入查找方式(1.按值查找  2.按序号查找):");
			ElemType num;
			scanf("%d", &num);
			if (num == 1)
			{
				ListSearch_Value();
				break;
			}
			if (num == 2)
			{
				ListSearch_Num();
				break;
			}
		}
		case 6:
		{
			ListTraverse();
			break;
		}
		case 7:
		{
			ListDestroy();
			break;
		}
		default:
			break;
		}
	}
}

4.运行结果

在这里插入图片描述

5.总结

单链表和顺序表都属于线性表,因此二者都具备线性表的特性,表中元素的数据类型都相同,每个元素占有相同大小的存储空间。
从上一篇的顺序表和这一篇的单链表中,对比可以看出,在查找数据和修改数据时,顺序表不需要移动数据,直接根据下标就可以查找对应的数据对其进行更新。而单链表中无论是查找还是更新,都必须从头开始遍历;但是对于从增加和删除,顺序表每次都要移动数据,而对于单链表来说,只需要修改指针的指向即可。
因此,总结来说,当对数据查找和修改操作比较频繁时,我们可以优先考虑顺序表,而对数据增加删除操作比较频繁时,可以优先考虑单链表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值