单链表的创建,插入与删除

一,什么是单链表

单链表是由结构体变量与结构体变量连接在一起的数据结构。

链表中的结构体是由数据域和指针域组成的, 而前一个结构体的指针域是指向下一个结构体的,从而将多个结构体连接起来,组成单链表。

struct Node
{
	int data;//结构域(存放数据)
	struct Node*next;//指针域(指向下一个结构体)
};

二,动态创建一个链表

动态创建一个链表是由动态内存申请和模块化设计(链表的功能,包含的数据)完成。

总的来说,创建一个链表是由一下五个步骤组成

1.创建链表(创建一个表头表示整个链表)

2.创建结点

3.插入结点

4.删除结点

5.打印遍历链表(测试)

1.创建链表

首先,我们应该创建一个表头来表示整个链表,代码如下

struct Node* createList()
{
	struct Node* headNode = (struct Node*)malloc(sizeof(Node));//使用malloc函数动态分配空间
	//headNode->data = 1;由于我们创建的是表头,二表头不存储数据,所以这里不需要数据域
	//headNode成为了一个结构体变量
	headNode->next = NULL;
	return headNode;
}

2.创建结点

这里创建结点和创建链表相似,只不过这里需要一个数据域,代码如下

struct Node* createNode(int data)
{
	struct Node* newNode = (struct Node*)malloc(sizeof(Node));
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

3.插入结点

插入节点总共有三种,分别为头插法,尾插法和指定位置插入。这里我们只讲头插法。

头插法,就是将一个新的结点插入表头的后面,使表头的指针域指向新的结点,而新的结点的指针域指向原本头结点指向的结点,代码如下

void insertNodeByHead(struct Node* headNode, int data)
{
	//首先,创建插入结点
	struct Node* newNode = createNode(data);
	newNode->next = headNode->next;//新的结点指向原来表头指向的结点
	headNode->next = newNode;//表头指向新结点
}

4.删除结点

删除结点,就是将指定的结点从链表中删除,而删除结点中用处最广泛的就是指定位置删除,而指定位置删除,本质上是从表头开始向后找,当遇到满足删除条件的结点,就将其从链表中删除,然后停止,所以,这种方法只能将离表头最近的满足条件的结点删除。所以说,如果链表有多个相同的结点,则要进行多次指定位置删除才可将所有满足条件的结点删除,也就是说每次删除最多只能删掉一个结点,代码如下

void deleteNodeByhead(struct Node* headNode, int posData)
{
	struct Node* posNode = headNode->next;//找出指定位置的结点
	struct Node* posNodeFront = headNode;//找出指定位置的前一个结点
	if (posNode == NULL)
	{
		printf("链表为空\n");
	}
	else
	{
		while (posNode->data != posData)//如果不符合要求,则向后寻找
		{
			posNodeFront = posNode;
			posNode = posNodeFront->next;
			if (posNode == NULL)
			{
				printf("没有找到相关信息,无法删除\n");
				break;
			}
		}
		posNodeFront->next = posNode->next;
		free(posNode);//删除该节点
	}
}

5.打印遍历链表(测试)

打印链表是从第二个结点开始打印,不包括表头,代码如下

void printList(struct Node* headNode)//打印以headNode为表头的链表
{
	struct Node* pMove = headNode->next;//定义一个移动的指针pMove,从第二个结点开始打印
	while (pMove)
	{
		printf("%d\n", pMove->data);//打印pMove中的数据
		pMove = pMove->next;//pMove向后走
	}
	printf("\n");
}

6.以下,我在主函数中尝试了插入和删除的相关操作,代码如下

int main()
{
	struct Node* list = createList();
	insertNodeByHead(list, 1);
	insertNodeByHead(list, 2);
	insertNodeByHead(list, 3);
	insertNodeByHead(list, 4);
	insertNodeByHead(list, 1);
	printList(list);
	deleteNodeByhead(list, 1);
	printList(list);
    system("pause");
	return 0;
}

下面是结果

下面就是全部代码

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


struct Node
{
	int data;//结构域
	struct Node*next;//指针域
};


struct Node* createList()
{
	struct Node* headNode = (struct Node*)malloc(sizeof(Node));//使用malloc函数动态分配空间
	//headNode->data = 1;由于我们创建的是表头,二表头不存储数据,所以这里不需要数据域
	//headNode成为了一个结构体变量
	headNode->next = NULL;
	return headNode;
}

struct Node* createNode(int data)
{
	struct Node* newNode = (struct Node*)malloc(sizeof(Node));
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}


void printList(struct Node* headNode)//打印以headNode为表头的链表
{
	struct Node* pMove = headNode->next;//定义一个移动的指针pMove,从第二个结点开始打印
	while (pMove)
	{
		printf("%d\n", pMove->data);//打印pMove中的数据
		pMove = pMove->next;//pMove向后走
	}
	printf("\n");
}

void insertNodeByHead(struct Node* headNode, int data)
{
	//首先,创建插入结点
	struct Node* newNode = createNode(data);
	newNode->next = headNode->next;//新的结点指向原来表头指向的结点
	headNode->next = newNode;//表头指向新结点
}

void deleteNodeByhead(struct Node* headNode, int posData)
{
	struct Node* posNode = headNode->next;//找出指定位置的结点
	struct Node* posNodeFront = headNode;//找出指定位置的前一个结点
	if (posNode == NULL)
	{
		printf("链表为空\n");
	}
	else
	{
		while (posNode->data != posData)//如果不符合要求,则向后寻找
		{
			posNodeFront = posNode;
			posNode = posNodeFront->next;
			if (posNode == NULL)
			{
				printf("没有找到相关信息,无法删除\n");
				break;
			}
		}
		posNodeFront->next = posNode->next;
		free(posNode);//删除该节点
	}
}



int main()
{
	struct Node* list = createList();
	insertNodeByHead(list, 1);
	insertNodeByHead(list, 2);
	insertNodeByHead(list, 3);
	insertNodeByHead(list, 4);
	insertNodeByHead(list, 1);
	printList(list);
	deleteNodeByhead(list, 1);
	printList(list);
	system("pause");
	return 0;
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值