C_12_链表

ops/2024/11/13 9:38:56/

链表

概述:

是一种数据结构

分为单链表与双链表两种

链表

链表种节点是离散的在内存中开辟空间的 因为是离散开辟,内存地址通常不是连续的,地址不一定相邻,甚至可能存在其他数据在它们之间。

在这里插入图片描述

链表

在这里插入图片描述

1 定义节点

分析:

一个节点就是一个结构体变量。

如:

链表节点

typedef struct node
{//数据域结构体成员变量;//int  age ;.....//地址域Node *next;
}Node;

链表节点

但是Node别名 是在下面定义的 内部怎么使用呢

typedef struct node
{//数据域结构体成员变量;//地址域
// Node *next;  // 但是 Node别名  是在下面定义的 内部怎么使用呢 
// Node *head;  // 使用别名就会报错//地址域  //解决 使用全名 也就是结构体 加结构体名struct node *next;struct node *head;
}Node;

2 组建链表节点

2.1 静态组建节点

#include <stdio.h>// 静态组建双链表节点typedef struct node
{// 数据域int num;// 地址域struct node *next;struct node *head;
} Node;
int main(int argc, char const *argv[])
{Node n01 = {1, NULL, NULL}; // 节点1Node n02 = {2, NULL, NULL}; // 节点2Node n03 = {3, NULL, NULL}; // 节点3n01.next = &n02;n02.head = &n01; // 1 2 链表进行关联上了n02.next = &n03;n03.head = &n02; // 2 3 链表进行关联上了// 链表遍历void print_link(Node * head){// 将首节点 赋值给当前节点Node *n = head;// 判断当前节点是否为NULLwhile (n != NULL){// 当前节点不为空,打印其数据printf("%d\n", n->num);// 移动当前节点到下一个节点n = n->next;}}print_link(&n01);printf("==============\n");print_link(&n02);return 0;
}

2.2 动态组建节点【*】

可以动态的操作 也就是局限性小

有序的 是指存的顺序 和取出顺序一样

就是怎么存的 怎么取的

比如 4 2 1 3 取出的时候 顺序也是 4 2 1 3

因为动态组建链表节点 是 使用 指针 所以

节点之间的链接方式,不应该使用取地址 & 操作,而应该直接使用节点指针。

>   n01->next = &n02;   错误的  >   n01->next = n02;    正确的

动态创建链表节点是和静态的创建节点是有区别的

#include <stdio.h>
#include <stdlib.h>
// 动态组建双链表节点
typedef struct node
{// 数据域int num;// 地址域struct node *next;struct node *head;
} Node;
int main(int argc, char const *argv[])
{Node *n01 = (Node *)calloc(1, sizeof(Node)); // 节点1Node *n02 = (Node *)calloc(1, sizeof(Node)); // 节点2Node *n03 = (Node *)calloc(1, sizeof(Node)); // 节点3// 判空if (n01 == NULL || n02 == NULL || n03 == NULL){return 0;}// 首先  头节点置空n01->head = NULL; // 1 链表的头节点置空// 节点之间的链接方式,不应该使用取地址 & 操作,而应该直接使用节点指针。  n01->next = &n02;   错误的n01->next = n02; // 1 2 链表就关联上了n02->next = n03;n03->head = n02; // 2 3 链表就关联上了// 尾节点置空n03->next = NULL;n01->num = 1;n02->num = 2;n03->num = 3;// 链表遍历void print_link(Node * head){// 将首节点 赋值给当前节点Node *n = head;// 判断当前节点是否为NULLwhile (1){// 当前节点不为空,打印其数据printf("%d\n", n->num);// 移动当前节点到下一个节点if (n->next == NULL){break;}n = n->next;}}// 遍历链表 方式2 void print_link1(Node * head){Node *jiedian = head;while (jiedian != NULL) // 只要有 节点就进行遍历{// 打印节点数据printf("节点数据为 %d\n", jiedian->num);// 节点往后移动一个jiedian = jiedian->next;}}printf("=======\n");
print_link(n01); // 传递的参数应该是节点指针 p,而不是节点指针的地址 &p。print_link1(n01);printf("=======\n");print_link(n03);printf("=======\n");print_link(n02);// 手动释放内存
free(n01);free(n02);free(n03);return 0;}

在这里插入图片描述

3 链表的操作

3.1 添加:

​ 目的: 链表尾部增加

​ 所需条件: 1 给谁添加 (首节点 head)

​ 2 要添加的节点 newNode

​ 函数:

/*
参数:head : 链表的第一个位置  就是首节点newNode: 要添加的节点
返回值 :链表的首节点
*/
// 链表的添加
Node *add_node(Node *head, Node *newNode)
{if (head == NULL){head = newNode;return head;}Node *n = head; // n 为设置的 当前节点while (n->next != NULL){n = n->next; // 将当前节点移动到下一节点}// 当循环结束后n就是最后一个节点 【要是单链表就结束了】n->next = newNode;// 将新节点的上一个节点设置为原来的最后一个节点 【双链表结束】newNode->head = n;return head;
}

优化:

/*
参数:head : 链表的第一个位置  就是首节点newNode: 要添加的节点
返回值 :链表的首节点
*/
Node*  add_node(Node *head,Node *newNode)
{
if(head == NULL)
{head = newNode;return head;
}
Node *n = head; //n 为设置的 当前节点
while( n->next != NULL)
{n = n->next;  //将当前节点移动到下一节点
}
//当循环结束后n就是最后一个节点 【要是单链表就结束了】n->next = newNode;  
//将新节点的上一个节点设置为原来的最后一个节点 【双链表结束】newNode->head = n;return head;
}

3.2 遍历

/*参数:head :要遍历的链表的首节点
*/
void print_link(Node *head) // 遍历节点
{// 将首节点 赋值给当前节点Node *n = head;// 判断当前节点是否为NULLwhile (n != NULL){// 当前节点不为空,打印其数据printf("%d\n", n->num);// 移动当前节点到下一个节点n = n->next;}
}

3.3 删除

/*
参数:head: 头节点delNode:要删除的节点
返回值:删除后链表的首节点
作用:删除指定节点
*/
Node *del_node(Node *head, Node *delNode)
{// 判断是否有首节点if (head == NULL){printf("没有首节点\n");return NULL;}// 判断要删除的节点是不是空的if (delNode == NULL){printf("要删除的节点为NULL\n");return head;}// 当要删除的节点就是首节点if (head == delNode){// 要删除的节点为首节点// 将下一个节点设为首节点head = head->next;// 将 先在的首节点的头节点 置空head->head = NULL;// 释放原来的首节点free(delNode);return head;}// 要删除的节点不是首节点,此时寻找要删除的节点// n 当前节点Node *n = head;while (n != delNode && n != NULL){n = n->next;}if (n == NULL){printf("没有要删除的节点");}//  判断要删除的节点就是最后一个节点的时候if (n->next == NULL){Node *headNode = n->head;headNode->next = NULL;free(n);return head;}// n就是要删除的节点Node *headNode = n->head;  // 取出n的上一个节点Node *nextNode = n->next;  // 取出n的下    一个节点free(n);                   // 释放nheadNode->next = nextNode; // 让n的上一个节点的下一个节点为n的下一个节点nextNode->head = headNode; // 让n的下一个节点的下一个节点为n的上一个节点return head;
}

3.4 修改

/*
参数:head:首节点 num:查找的值newNum:修改后的值
返回值:
无  
作用: 
按值 按位 修改指定节点的值   
// 按值 修改
#include <stdio.h>
void update_link(Node *head, int num, int newNum)
{Node *n = find_link(head, num);if (n == NULL){return;}n->num = newNum;
}
/*
作用:按位置修改指定节点的值
参数:head:首节点index:修改的位置newNum:修改后的值
返回值:无
*/
void update_i(Node *head, int index, int newNum)
{Node *n = find_i(head, index);if (n == NULL){return;}n->num = newNum;
}	

3.5 插入

目的:随意位置插入

/*
参数:head:  首节点index   要插入的节点位置newNode 新节点返回值:插入后首节点
作用:按位置插入新节点*/
// 思路  按你想要插入的位置插入
Node *insertlink(Node *head, int index, Node *newNode)
{if (index == 0){newNdode->next = head;head->head = newNode;head = newNode;return head;}// index 位置原来的节点Node *n = find_index_link(head, index){Node *n = find_index_link(head, index);if (n == NULL){add_link(head, newNode);// add_link  是添加  链表节点 函数return head;}Node *headNode = n->head;headNode->next = newNode;newNode->head = headNode;newNode->next = n;n->head = newNode;return head;}}

获取链表长度

/*
参数:首节点
作用:获取链表长度
返回值:链表长度
*/
int get_len(Node *head)
{int i = 0;Node *n = head;while (n != NULL){i++;n = n->next;}return i;
}

3.6 查找

按位置进行查找节点

  • 1 按值查找
  • 2 按位查找
/*
作用:按结构体中存储的值查找对应的节点
参数:head:首节点num:查找的值
返回值:查询到的节点,如果为NULL证明不存在
*/
//【 1 按值查找 】
Node * find_link(Node * head,int num)
{Ndoe *n =head;while(n != NULL){if(n-> num == num){return n;}n = n->next;}return NULL;
}
// 【 2 按位查找 】
/*
作用:
按结构体在链表中的位置查找对应的节点
参数:
head:首节点
index:下标
返回值:
查询到的节点,如果为NULL证明不存在
*/
Node *find_i(Node *head, int index)
{Node *n = head;int i = 0;while (n != NULL){if (i == index){return n;}n = n->next;i++;}return NULL;
}

3.7 逆序

#include <stdio.h>
// 逆序排列
void print_link_r(Node *head)
{int len = get_len(head);int index = len - 1; // 下标就是长度减一 就是最后一位的下标Node *n = find_i(head, index);while (n != NULL){printf("%d\n", n->num);n = n->head;}
}

3.8 排序

顺序

Node *sort_link(Node *head)
{if (head == NULL){return NULL;}int len = get_len(head);for (int i = 0; i < len; i++){for (int j = 0; j < len - 1; j++){Node *n = find_i(head, j);Node *nn = n->next;if (n->num > nn->num){if (j == 0){Node *nnn = nn->next;nn->next = n;n->head = nn;nn->head = NULL;n->next = nnn;nnn->head = n;head = nn;}else if (j == len - 2){Node *hn = n->head; // 倒数第三个节点hn->next = nn;nn->head = hn;nn->next = n;n->head = nn;n->next = NULL;}else{Node *hn = n->head;Node *nnn = nn->next;hn->next = nn;nn->head = hn;nn->next = n;n->head = nn;n->next = nnn;nnn->head = n;}}}}return head;
}

逆序排列

//逆序排列
void print_link_desc(Node *head)
{int len = get_len(head);int index =len-1 ;   // 下标就是长度减一 就是最后一位的下标Node *n = find_i(head,index);while (n != NULL){printf("%d\n",n->num);n = n->head;}
}

3.9 释放

#include <stdio.h>
void free_link(Node *head)
{Node *n = head;while (n != NULL){Node *nextNode = n->next;free(n);n = nextNode;}
}

http://www.ppmy.cn/ops/105263.html

相关文章

Anaconda的包管理

使用pip命令安装第三方包的方法&#xff0c;其中package-name代表程序包的名字 pip install package-name使用conda下载Python程序包 conda install package-name使用conda list可以查看有哪些包是使用conda进行安装的。 使用pip list可以查看有哪些包是使用pip进行安装的。

【STM32】FMC

FMC功能与FSMC类似&#xff0c;但比FSMC更强大&#xff0c;但仅在F4 / F7 / H7等高级一点的MCU上支持&#xff0c;F1不支持。虽然我的是F103&#xff0c;但顺便都看了。 大部分图片来源&#xff1a;正点原子HAL库课程 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目…

【人工智能】项目案例分析:使用TensorFlow进行大规模对象检测

&#x1f3c6;&#x1f3c6;欢迎大家来到我们的天空&#x1f3c6;&#x1f3c6; &#x1f3c6; 作者简介&#xff1a;我们的天空 &#x1f3c6;《头衔》&#xff1a;大厂高级软件测试工程师&#xff0c;阿里云开发者社区专家博主&#xff0c;CSDN人工智能领域新星创作者。 &…

Pixelmator Pro for Mac 专业图像处理软件【媲美PS的修图软件】

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件…

win10配置adb环境变量

初始状态&#xff1a; 最简单的配置方案&#xff0c;直接复制adb所在路径&#xff1a; 粘贴进来确定即可&#xff1a; 然后打开 cmd 查看已经配置成功了&#xff1a;

如何本地搭建Whisper语音识别模型

Whisper是OpenAI推出的一款强大的语音识别模型,具备多种语言的识别能力。尽管基于云的语音识别服务方便,但有些项目和需求需要在本地环境运行,以确保数据隐私和降低延迟。以下是如何在本地搭建Whisper语音识别模型的详细指南。 环境准备 1. 硬件要求: - 计算能力:建议…

python-A-B数对

题目描述 给出一串数以及一个数字 C&#xff0c;要求计算出所有 A−BC 的数对的个数&#xff08;不同位置的数字一样的数对算不同的数对&#xff09;。输入 输入共两行。 第一行&#xff0c;两个整数 N,C。 第二行&#xff0c;N 个整数&#xff0c;作为要求处理的那串数。输出 …

001.Python爬虫系列_网络基础

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数…