嵌入式C语言基础知识查漏补缺 -- 链表

 单链表:

结构体变量通过结构体指针连接在一起。

                /*链表的结构体*/
#include <stdio.h>

typedef struct Node{
    int data;               //数据域,可以是任何类型的数据
    struct Node* next;      //指针域
}Node, *LinkedList;

其中,Node表示结点的类型,LinkedList表示指向Node结点类型的指针类型。

分类:

  • 静态链表:链表分配在栈上;
  • 动态链表:链表分配在堆上。

静态链表:

int main()
{
	//结点创建
	Node node1 = { 10,NULL };
	Node node2 = { 20,NULL };
	Node node3 = { 30,NULL };

	//建立结点之间的关系
	node1.next = &node2;
	node2.next = &node3;

	//遍历链表
	struct Node* pCurrent = &node1;
	while (pCurrent != NULL)
	{
		printf("%d\n", pCurrent->data);
		pCurrent = pCurrent->next;
	}

    return 0;
}

动态链表:

int main()
{
	# 结点创建
	Node* node1 = (Node*)malloc(sizeof(Node));
	Node* node2 = (Node*)malloc(sizeof(Node));
	Node* node3 = (Node*)malloc(sizeof(Node));

	# 给每个结点建立关系并给数据域赋值
	node1->data = 10;
	node1->next = node2;
	node2->data = 20;
	node2->next = node3;
	node3->data = 30;
	node3->next = NULL;

	# 遍历链表
	struct Node* pCurrent = node1;
	while (pCurrent != NULL)
	{
		printf("%d\n", pCurrent->data);
		pCurrent = pCurrent->next;
	}

    return 0;
}

单链表的基本使用:

(1)初始化链表:

具有返回值,该函数的返回值是: 创建好的链表的头结点。

# 初始化链表
# 函数的返回值是 创建好的链表的头结点
LinkedList init_LinkList()
{
    # malloc()函数返回的为void*类型,需强转为Node*类型。
	Node* pHeader = (Node*)malloc(sizeof(Node));
	if (pHeader == NULL)
	{
		return NULL;
	}	
	//pHeader->num = -1;    //头结点初始化,一般不需要维护数据域
 	pHeader->next = NULL;   //初始化一个空链表

	# 创建一个结点指针,用于记录当前链表节点的位置,方便做尾插
	Node* pCurrent = pHeader;

	int val = -1;
	while (1)
	{
		printf("请输入数据,-1代表结束\n");
		scanf("%d", &val);
		if (val == -1)
		{
			break;
		}

		# 创建新节点
		Node* newNode = (Node*)malloc(sizeof(Node));
		newNode->data = val;
		newNode->next = NULL;

		# 更新节点指向
		pHeader->next = newNode;
		pCurrent = newNode;
	}
	return pHeader;
}

(2)遍历链表:

void print_List(LinkedList pHeader)
{
	if (pHeader == NULL)  //如果该节点为空,则不遍历
	{
		return;
	}
	//当前节点,指向第一个有真实数据的节点
	Node* pCurrent = pHeader->next;
	while(pCurrent != NULL)
	{
		printf("%d\n", pCurrent->data);
		pCurrent = pCurrent->next;
	}
    printf("\n");
}

简单的遍历设计的函数只需要void无参即可,而当涉及到元素操作时,可以设计一个LinkedList类型的函数,使其返回一个操作后的新链表。

(3)链表结点的插入:

链表的插入操作主要分为:

  • 查找到第i个位置;
  • 将该位置的next指针修改为指向我们新插入的结点;
  • 新插入的结点next指针指向i+1位置的结点。

利用两个辅助指针变量实现链表的插入:

① 在 oldval 前插入 newvalue,如果 oldval 不存在,则做尾插。

LinkedList insert_Linklist(LinkedList pHeader, int oldVal, int newVal)
{
	if (pHeader == NULL)
	{
		return;
	}

    //创建两个临时指针事项节点插入
	Node* pPre = pHeader;
	Node* pCurrent = pHeader->next;

	while (pCurrent != NULL)
	{
		if (pCurrent->data == oldVal)
		{
			break;
		}
		//两个辅助指针向后移动
		pPre = pCurrent;
		pCurrent = pCurrent->next;
	}

	//创建新节点
	Node* newNode = (Node*)malloc(sizeof(Node));
	newNode->data = newVal;
	newNode->next = pCurrent;

	pPre->next = newNode; 
    
    return pHeader; 
}

② 在第 i 个位置插入值为 x 的结点。

LinkedList insert_Linklist(LinkedList pHeader, int i, int x)
{
	if (pHeader == NULL)
	{
		return;
	}

	Node* pPre = pHeader;
    for(int tmp=1; tmp<i;tmp++)
    {
        pPre = pPre->next;    //查找第i个位置的前驱结点
    }

	//创建新节点
	Node* newNode = (Node*)malloc(sizeof(Node));
	newNode->data = x;
	newNode->next = pPre->next; 

	pPre->next = newNode; 

    return pHeader;
}

(4)删除节点

# 函数参数列表里的 struct Node* pHeader 也可以写成 LinkedList pHeader
LinkedList delete_LinkList(struct Node* pHeader, int delVal)  
{
	if (pHeader == NULL)
	{
		return;
	}
	Node* pPre = pHeader;
	Node* pCurrent = pHeader->next;

	while (pCurrent != NULL)
	{
		if (pCurrent->data == delVal)
		{
			break;
		}
		//移动两个辅助指针来遍历链表
		pPre = pCurrent;
		pCurrent = pCurrent->next;
	}
	if (pCurrent == NULL)
	{
		//没有找到用户需要删除的节点
		return;
	}
	pPre->next = pCurrent->next;
	free(pCurrent);
	//pCurrent = NULL;
}

(5) 反转链表

void reverse_LinkList(LinkedList pHeader)
{
    if (pHeader == NULL)
    {
        return;
    }
    LinkedList pPrev = NULL;
    LinkedList pCurrent = pHeader->next;
    LinkedList pNext = NULL;

    while (pCurrent != NULL)
    {
        pNext = pCurrent->next;
        pCurrent->next = pPrev;
        pPrev = pCurrent;
        pCurrent = pNext;
    }
    pHeader->next = pPrev;
}

(6)测试程序

int main(void)
{
    Node* pHeader = init_LinkList();
    printf("初始链表为:\n");
    print_List(pHeader);
    reverse_LinkList(pHeader);
    printf("反转后链表为:\n");
    print_List(pHeader);

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值