单链表之无头链表(C语言版)

单链表之无头链表

在这里插入图片描述
1. 定义节点结构

  • NODE为 节点类型
  • LPNODE 为节点指针类型
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

//定义节点结构
typedef struct Node_tlg{
	int data;         //数据域
	struct Node_tlg* next; //指针域
}NODE,*LPNODE;

节点结构

2. 定义链表结构

  • size 当前节点个数
  • frontNode 首元节点指针
  • tailNode 尾节点指针
  • List 链表数据类型
//定义链表结构
typedef struct List_tlg{
	int   size;        //当前节点个数
	NODE* frontNode;   //首元节点(头节点)指针
	//LPNODE frontNode;  也可
	NODE* tailNode;    //尾节点指针
}List;

3. 创建链表

//创建链表
List* createList()
{
	List* list = (List*)malloc(sizeof(List));
	if (NULL == list)
	{
		printf("链表空间申请失败!\n");
		return NULL;
	}
	//初始化链表数据
	list->size = 0;
	list->frontNode = NULL;
	list->tailNode = NULL;
	return list;
}

4. 创建节点

//创建节点
LPNODE createNode(int data)
{
	LPNODE newNode = (LPNODE)malloc(sizeof(NODE));
	if (NULL == newNode)
	{
		printf("节点空间申请失败!\n");
		return NULL;
	}
	//初始化节点数据
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

5. 求链表长度

//求链表长度大小
int listSize(List* list)
{
	return list->size;
}

6. 判断链表是否为空

//求链表是否为空
int empty(List* list)
{
	return list->size == 0;
}

7. 头插法插入数据

  • 为空直接插入即可

       1. 头节点指针(frontNode),尾节点指针(tailNode)均指向新节点
    
  • 不为空头插法插入数据

     1. 新节点(newNode)指针域指向首元节点
     2. frontNode(链表首元节点)指针移动到新节点(newNode)
    
//头部插入
void insertFront(List* list, int data)
{
	//创建一个节点
	LPNODE newNode = createNode(data);
	//表为空直接插入
	if (empty(list))
	{
		//头指针尾指针均指向创建的新节点
		list->frontNode = newNode;
		list->tailNode = newNode;
	}
	//头插,移动头节点指针
	else{
		newNode->next = list->frontNode;
		list->frontNode = newNode;
	}
	list->size++;
}

头插法插入数据

8. 尾插法插入数据

  • 为空直接插入即可

       1. 头节点指针,尾节点指针均指向新节点
    
  • 不为空头插法插入数据

     1. 尾节点(tailNode)的next域指向新节点(newNode)
     2. tailNode(链表尾节点)指针移动到新节点(newNode)
    
//尾部插入
void insertTail(List* list, int data)
{
	//创建一个节点
	LPNODE newNode = createNode(data);
	//为空直接插入
	if (empty(list))
	{
		list->frontNode = newNode;
		list->tailNode = newNode;
	}
	//插入节点到尾部,移动尾指针
	else{
		list->tailNode->next = newNode;
		list->tailNode = newNode;  
	}
	list->size++;
}

尾插法插入数据

9. 自定义位置插入数据

//自定义位置插入
void insertAppoint(List* list, int data, int pos)
{
	//创建一个节点
	LPNODE newNode = createNode(data);
	LPNODE curNode = list->frontNode;
	LPNODE beforeNode = NULL;
	if (pos > list->size || pos <= 0)
	{
		printf("插入的位置有误!\n");
		return;
	}
	if (pos == 1)   //头插
	{
		insertFront(list, data);
		return;
	}
	while (--pos && curNode->next!=NULL)
	{
		beforeNode = curNode;
		curNode = curNode->next;
	}
	newNode->next = curNode;
	beforeNode->next = newNode;
	list->size++;
}

指定位置插入数据

10. 头删法删除数据

  • 只有一个节点

    	 1. 直接删除
    	 2. 将首元节点指针(frontNode),尾节点指针(tailNode)置空即可
    
  • 头删法删除

       1. 保存要删除的节点(定义一个节点保存首元节点)
       2. 首元节点指针(frontNode)指向首元节点(或要删除节点)下一个节点
       3. 删除保存的节点
    
//头部删除
void deleteFront(List* list)
{
	if (empty(list))
	{
		printf("表为空,无元素可删!\n");
		return;
	}
	if (listSize(list) == 1)
	{
		LPNODE delNode = list->frontNode;
		free(delNode);
		delNode = NULL;
		list->frontNode = NULL;
		list->tailNode = NULL;
	}
	else{
		LPNODE delNode = list->frontNode;
		list->frontNode = delNode->next;
		free(delNode);
		delNode = NULL;
	}
	list->size--;
}

头删法删除节点

11. 尾删法删除数据

  • 只有一个节点

        1. 直接删除
        2. 将首元节点指针(frontNode),尾节点指针(tailNode)置空即可
    
  • 尾删法删除

       1. 保存要删除的节点(定义一个节点保存最后一个节点delNode)
       2. 定义一个节点去保存需要删除节点的前一个节点(curNode)
       3. 尾节点指针(tailNode)指向curNode节点
       4. 删除保存的节点(delNode)
    
//尾部删除
void deleteTail(List* list)
{
	if (empty(list))
	{
		printf("表为空,无元素可删!\n");
		return;
	}
	if (listSize(list) == 1)
	{
		LPNODE delNode = list->tailNode;
		free(delNode);
		delNode = NULL;
		list->frontNode = NULL;
		list->tailNode = NULL;
	}
	else
	{
		LPNODE delNode = list->tailNode;
		LPNODE curNode = list->frontNode;  //保存删除节点的前一个节点
		while (curNode->next->next != NULL)
		{
			curNode = curNode->next;
		}
		list->tailNode = curNode;
		free(delNode);
		delNode = NULL;
		curNode->next = NULL;
	}
	list->size--;
}

尾删法删除节点

12. 自定义位置删除数据

//自定义位置删除
void deleteAppoint(List* list, int pos)
{
	if (empty(list))
	{
		printf("表为空,无元素可删!\n");
		return;
	}
	LPNODE delNode = list->frontNode;
	LPNODE curNode = NULL;
	if (pos == 1)   //pos为1直接头删
	{
		deleteFront(list);
		return;
	}
	while (--pos > 0 && delNode->next != NULL)
	{
		curNode = delNode;
		delNode = delNode->next;
	}
	if (curNode == NULL)
	{
		printf("节点删除失败!可能位置有误哦!\n");
		return;
	}
	curNode->next = delNode->next;
	free(delNode);
	delNode = NULL;
	list->size--;
}

13. 删除指定数据

//指定数据删除
void deleteByData(List* list, int data)
{
   //判断链表中是否有用户想要删除的数据的标志
	bool flag = false;
	if (empty(list))
	{
		printf("表为空,无元素可删!\n");
		return;
	}
	LPNODE delNode = list->frontNode;
	LPNODE curNode = NULL;
	while (delNode->next!=NULL)
	{
		curNode = delNode;
		delNode = delNode->next;
		if (delNode->data == data)
		{
		//找到数据,标志置为true,退出循环
			flag = true;  
			break;
		}
	}
	//节点删除
	if (flag){
		curNode->next = delNode->next;
		free(delNode);
		delNode = NULL;
		list->size--;
	}
	else
	{
		printf("表中没有你想要删除的数据!\n");
		return;
	}
}

14. 清空链表

//清空链表
void clearList(List* list)
{
	int n = listSize(list);
	while (n--)
	{
		//头删删除链表中的节点
		deleteFront(list);
	}
	if (list->size == 0)
	{
		printf("链表已清空!\n");
		return;
	}
	else{
		printf("链表未清空!\n");
		clearList(list);
	}
}

15. 销毁链表

//销毁链表
//注意改变指针指向需要传入二级指针
void destoryList(List** plist)
{
	if ((*plist)->size >= 0)
	{
		clearList(*plist);
	}
	free(*plist);
	*plist = NULL;
	printf("链表已经销毁!\n");
}

16. 打印链表

//打印链表
void showList(List* list,char* str)
{
	printf("%s\n", str);
	if (listSize(list) == 0 || list == NULL)
	{
		printf("链表为空,无法打印!\n");
		return;
	}
	LPNODE curNode = list->frontNode;
	while (curNode != NULL)
	{
		printf("%d\t", curNode->data);
		curNode = curNode->next;
	}
	//打印当前链表长度
	printf("\n当前链表长度: %d", list->size);
	putchar('\n');
	putchar('\n');
}

17.链表功能测试

int main()
{
	system("color 0B");
	//创建无头链表
	List* mylist = createList();
	//头插
	for (int i = 0; i < 10; i++)
	{
		insertFront(mylist, 520 + i);
	}
	showList(mylist,"头插: ");
	//尾插
	for (int i = 0; i < 5; i++)
	{
		insertTail(mylist, 580 + i);
	}
	showList(mylist,"尾插: ");
	//头删
	deleteFront(mylist);
	showList(mylist,"头删: ");
	//尾删
	deleteTail(mylist);
	showList(mylist,"尾删: ");
	//自定义位置插入
	insertAppoint(mylist,1314,2);
	showList(mylist,"自定义位置插入: ");
	//自定义位置删除
	deleteAppoint(mylist, 2);
	showList(mylist,"自定义位置删除: ");
	//指定数据删除
	deleteByData(mylist, 1000);
	showList(mylist, "指定数据删除: ");
	//清空链表
	clearList(mylist);
	//销毁链表
	destoryList(&mylist);  //二级指针传入改变指针指向

	system("pause");
	return 0;
}

测试数据

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

石小浪♪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值