线性表-LinkList(单链表)
知识点 1:顺序存储结构需要预分配存储空间。单链表不需要分配存储空间,元素限制不受控制
2:选择顺序存储结构-线性表需要频繁查找,很少进行插入和删除操作。使用单链表结构-元素个数变化较大或者根本不知道有多大时
3:链表改不改变,应该准确理解为链表头指针地址是否改变。
增、删、改的是非头结点时,加不加&符号,原链表都会相应改变;但一旦头指针改变,没加&符号的函数会导致程序出错;
所以一般写增加、删除、插入节点的函数时,为了保证涉及到头指针的修改不出错(尤其是不带头结点的链表),都需要加上&。
链表的第一个结点明确知道是不会改变的,故头指针地址不会改变,所以不用加&。
4:
1)传值方式传参
①传地址:
在函数中如果传递的是指针,那么只能修改指针指向的内容,不能修改指针本身;如果想要修改指针本身,要么在再加一级指针,要么用引用&。
②引用传参:
引用传参往往要比值传参高效,因为它是直接将x作为参数传入进去,而少了对x进行复制这部分的开销,既然传入进去的是x,那么对x的修改肯定也生效
2)引用方式传参引用可以被理解为变量的一个别名,但这依旧是原变量,如果在函数内对该变量进行修改的话,在外部该变量也会相应被修改。
总结
在传值方式传参时,对于基本类型:函数参数为int x,调用函数传入x;对于指针:函数参数为LNode *,调用函数时传入L
在地址传递时,对于基本类型:函数参数为int *x,调用函数传入&x;对于指针:函数参数为LNode **,调用函数时传入&L。
在引用方式传参,对于基本类型:函数参数为int &x,调用函数传入x;对于指针:函数参数为LNode* &L(或LinkList &L ),调用函数时传入&L。
typedef struct Link { int elem; struct Link *next;//指针域 }LinkNode,*LinkList; //以下新建节点等价 //LinkNode *tnode1 = (linkNode *)malloc(sizeof(linkNode)); //LinkList tnode = (LinkList)malloc(sizeof(linkNode));
创建头结点
LinkList createLinkListHead() { LinkList head = (LinkList) malloc(sizeof(LinkNode)); head->next = NULL; return head; }
带头结点的头插法
void insertHeadLinkList(LinkList head, int value) { LinkList node = (LinkList) malloc(sizeof(LinkNode)); node->elem = value; node->next = head->next; head->next = node; }
尾插法
void insertLastLinkList(LinkList head, int value) { LinkList temp = head; while (temp->next != NULL) //找到末尾结点 temp = temp->next; LinkList node = (LinkList) malloc(sizeof(LinkNode)); node->elem = value; temp->next = node; node->next = NULL; }
插入指定位置
void insertPositionLinkList(LinkList head, int position, int value) { if (position < 0) //-1 从末尾添加,采用尾插法 insertLastLinkList(head,value); else if (position == 0) //从第一个结点插入,采用头插法 insertHeadLinkList(head,value); else { // LinkList temp = head->next; while (temp != NULL && --position > 0) { //找到合适的位置结点 temp = temp->next; } LinkList node = (LinkList) malloc(sizeof(LinkNode)); node->elem = value; node->next = temp->next; temp->next = node; } }
删除指定位置节点
void deletePositionLinkList(LinkList head, int position) { if (position < 0) { printf("指定下标值不正确\n"); return; } LinkList node = head; int i = 0; while (!node->next || i < position) { //寻找指定下标的节点,结束循环时,i==position node = node->next; i++; } if (i == position) { //找到指定节点 LinkList temp = node->next; //temp 是要被删除的节点 node->next = temp->next; temp->next = NULL; printf("该位置值为%d\n",temp->elem); free(temp); } else { //没找到 printf("没找到指定下标的值"); } }
删除指定数据节点
void deleteValueLinkList(LinkList head, int value) { LinkList node = head; while (!node->next) { if (node->next->elem == value)break;//找到前节点 node = node->next; } if (node->next != NULL) { //找到要删除的节点 LinkList temp = node->next; //temp 是要被删除的节点 node->next = temp->next; temp->next = NULL; free(temp); } else { printf("没找到要删除的节点\n"); } }
销毁链表
void destoryLinkList(LinkList head) { while (head->next != NULL) { LinkList node = head->next; head->next = node->next; free(node); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?