(不带头结点的)单链表增删查改,逆置单链表(两种方法),求两个单链表的第一个公共结点,合并两个单链表,单循环链表中判断第一个入环点,约瑟夫环
补充了每个算法的基本思想,并且画了思路图,源代码都经过调试成功
1.SlistNode.c文件
(1) (不带头结点的)单链表增删查改
#include "SlistNode.h"SlistNode* slistBuyNode(int x) //申请新的值为x的节点
{SlistNode *t = (SlistNode*)malloc(sizeof(SlistNode));t->data = x;t->next = NULL;return t;
}void slistInit(SlistNode **p) //初始化
{(*p)= NULL;
}void slistPrint(SlistNode*p) //打印
{SlistNode* t = p;for (t = p; t; t = t->next){printf("%d->", t->data);}printf("NULL\n");
}
SlistNode* slistFind(SlistNode*p, int x) //查找x
{SlistNode* t = p;for (t = p; t; t = t->next){if (t->data == x)return t;}return NULL;
}void slistInsert(SlistNode**pos, int x) //在pos后插入
{SlistNode*t = slistBuyNode(x);t->next = (*pos)->next;(*pos)->next = t;
}void slistEraseAfter(SlistNode**p,int x) //删除x
{SlistNode*t = *p,*t1;if ((*p)->data == x) //要删除的值x是第一个结点时{t1 = *p; //临时备份*p = t1->next;free(t1);t1 = NULL;}for (t = *p; t&&t->next; t = t->next) //要删除的值x不是第一个结点时{if (t->next->data == x) //t->next即从第二个结点开始扫描{t1 = t->next;t->next = t1->next;free(t1);t1 = NULL;}}return 1;
}void slistPushFront(SlistNode**p, int x) //头插
{ SlistNode*t = slistBuyNode(x);t->next = (*p);(*p) = t;
}void slistPopFront(SlistNode**p) //头删
{SlistNode *t;if ((*p) == NULL)return;t = (*p)->next;free((*p));*p = t;return;
}void slistDestory(SlistNode **p) //销毁
{SlistNode *t = *p;if ((*p) == NULL)return ;while ((*p)->next != NULL){(*p)->next = (*p)->next->next;//不停地后删,直到删光所有结点free(*p);*p = NULL; //防止野指针}
}void removeall(SlistNode**p, int x) //删除所有值为X的结点
{SlistNode *t, *t1;if ((*p) == NULL)return NULL;if (((*p)->data == x)) //要删除的x是第一个结点时{t = (*p);t1 = t;*p =t1->next;free(t1);t1 = NULL;}t = *p; //执行完上述操作之后t指向的原来的*p被释放了,所以要让t指向新的头while (t->next&&t) //这里用一个while和if-else循环将从第二个结点开始的所有与{ //x相同的结点删除。if (t->next->data == x) //t->next即从第二个结点开始扫描{t1 = t->next;t->next = t1->next;free(t1);t1 = NULL;}elset = t->next;}
}
(2)逆置单链表(两种方法)
方法一:先后删,别释放,再头插。具体可以如下图所示。
void reverse1(SlistNode**p) //逆置单链表
{SlistNode*t; //当前操作的结点SlistNode*h; //指向新的头结点SlistNode*oldh; //一直指向旧的头结点oldh = *p;h = oldh;t = oldh->next;while(t){oldh->next = t->next; //后删t->next = h; //头插h = t;t = oldh->next;}*p = h; // 最后的新头是h
}
方法二:断结点,向后转,具体如图:
void reverse2(SlistNode**p) //逆置单链表2{SlistNode*h, *c, *t;h = *p;c = h->next;t = c;h->next = NULL;while (t){t = t->next;c->next = h;h = c;c = t;}*p = h;
}
(3)求两个单链表的第一个公共结点
int comnode(SlistNode**LA, SlistNode**LB) //两个链表公共结点
{SlistNode*A = *LA, *B = *LB;int lenA = 0, lenB = 0,gap=0;for (A = *LA; A; A = A->next)lenA++;for (B = *LB; B; B = B->next)lenB++;A = *LA; B = *LB; //上述操作之后A与B的指向均已发生变化。gap = abs(lenA - lenB);if (lenB > lenA){A = *LB;B = *LA;}for (int i = 0; i < gap; i++)A = A->next;for (; A&&B; A = A->next, B = B->next)if (A->data == B->data) //这里不能是两个指针变量比较return A->data;return NULL;
}
(4)合并两个单链表
SlistNode* merge(SlistNode**LA, SlistNode**LB) //合并两个单链表
{SlistNode*preA = *LA, *L = preA,*A = preA->next, *B = *LB, *nextB = B->next;while( preA&&A&&nextB&&B){if (preA->data > B->data){B->next = preA; //插入B = nextB;nextB = B->next; }if (A->data > B->data){B->next = A;preA->next = B; //插入BpreA = B; //插入的B在preA和A之间B = nextB;nextB = nextB->next;}else if (A->data <= B->data){preA = A;A=preA->next;}}while (nextB)//A为空且B不为空时{A->next = B;B = nextB;}free(B);B = NULL;return L;
}
(5)单循环链表中判断第一个入环点
SlistNode* cycle(SlistNode**h) //单循环链表中判断第一个入环点
{SlistNode*fast=*h, *slow=fast;while (fast&&slow) //找相遇点{fast = fast->next->next;slow = slow->next;if (fast == slow)break;}for (; fast->next && (*h)->next; fast = fast->next, (*h) = (*h)->next)if (fast == *h)return fast;return NULL;
}
(6)约瑟夫环
SlistNode* Josephus(SlistNode**l,int n,int m) //约瑟夫环
{SlistNode *p, *prep;p = *l; prep = p;while (p->next!= *l){p = p->next; //p指向尾结点}prep = p; //prep指向尾结点p = p->next; //p指向第一个结点while (p&&prep&&n>1){for (int i = 0; i < m-1; i++) //从第一个结点开始报数,则报到第m个结点时,走了m-1步{prep = p;p = p->next;}prep->next = p->next;free(p);p=prep;p = p->next;n--;}return p;
}
**
2.SlistNode.h文件
**
#ifndef _SLISTNODE_H_
#define _SLISTNODE_H_#include <stdio.h>
#include<windows.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>typedef struct SlistNode
{int data;struct SlistNode* next;
}SlistNode;
void slistPrint(SlistNode *p);
void slistInit(SlistNode **p);
void slistDestory(SlistNode **p);
SlistNode* slistBuyNode(int x);void slistPopFront(SlistNode**p);
void slistPushFront(SlistNode**p, int x);SlistNode* slistFind(SlistNode*p, int x);void slistInsert(SlistNode**pos,int x);
void slistEraseAfter(SlistNode**p,int x);void removeall(SlistNode**p, int x);void reverse1(SlistNode**p);
void reverse2(SlistNode**p);int comnode(SlistNode**LA, SlistNode**LB);
SlistNode* cycle(SlistNode**h);
SlistNode* merge(SlistNode**LA, SlistNode**LB);
SlistNode* Josephus(SlistNode**l, int n, int m);
#endif
3.main.c文件
#include "SlistNode.h"
int main()
{SlistNode *p;slistInit(&p);slistPushFront(&p, 10);slistPushFront(&p, 9);slistPushFront(&p, 6);slistPushFront(&p, 5);slistPushFront(&p, 4);slistPushFront(&p, 1);//slistPopFront(&p);//slistInsert(&(p->next->next), 9);slistPrint(p);//slistEraseAfter(&p,3);//SlistNode*t = slistFind(p, 3); printf("%d", t->data);//removeall(&p, 3);//reverse1(&p);//reverse2(&p);/* SlistNode *q;slistInit(&q);slistPushFront(&q, 10);slistPushFront(&q, 9);slistPushFront(&q, 8);slistPushFront(&q, 7);slistPrint(q);*//*int r=comnode(&p, &q);printf("%d\n", r);*/SlistNode*r=p, *h;while (r->next)r = r->next;r->next = p; //围成一个循环圈:1-2-3-4-5-1-2-3-4-5-1-2-3-4-5...... //r->next = p->next; 第一个结点在外边,其他结点围成循环:1-2-3-4-5-2-3-4-5-2-3-4-5....//slistPrint(p);/*h=cycle(&p);printf("%d\n", h->data); *///SlistNode*t=Josephus(&p, 6, 3);//slistPrint(t);//SlistNode*t=merge(&p, &q);//slistPrint(t);system("pause");return 0;
}
(不带头结点的)单链表增删查改,逆置单链表(两种方法),求两个单链表的第一个公共结点,合并两个单链表,单循环链表中判断第一个入环点,约瑟夫环相关推荐
- 单链表反转(逆置)——(四种方法实现)
链表逆置就是把最后一个数据提到最前面,倒数第二个放到第二个--依次类推,直到第一个到最后一个. 由于链表没有下标,所以不能借助下标来实行数据的逆置,要靠空间的转移来完成链表的逆置,这里采用没有头节点的 ...
- C++ 链表 增删查改
#if 1 #include<algorithm> #include<iostream> #include<vector> using namespace std; ...
- 约瑟夫环 java_约瑟夫环Java实现
/** * 约瑟夫问题 * 设编号为 1,2,- n 的 n 个人围坐一圈, * 约定编号为 k(1<=k<=n)的人从 1 开始报数, * 数到 m 的那个人出列, * 它的下一位又从 ...
- 用C语言编写约瑟夫环程序,约瑟夫环C语言,请高手检查我的程序
/*TC2编译通过*//*测试了几组数据,没有发现问题*//*如果有问题,再M我*/#include typedef struct Cnode {int data; int password; str ...
- 数据结构之单链表的增删查改等操作画图详解
单链表 文章目录 单链表 链表的概念及其结构 概念 结构 链表的实现 开辟一个新结点 链表的销毁 打印链表 单链表的尾插 单链表的头插 单链表的头删 单链表的尾删 找到单链表中的一个结点 在pos位置 ...
- js删除指定html及子标签,js中如何删除某个元素下面的所有子元素?(两种方法)...
js中如何删除某个元素下面的所有子元素?(两种方法) 一.总结 方法一:通过元素的innerHTML属性 元素element.innerHTML=""; 方法二:通过元素的remo ...
- ML:模型训练/模型评估中常用的两种方法代码实现(留一法一次性切分训练和K折交叉验证训练)
ML:模型训练/模型评估中常用的两种方法代码实现(留一法一次性切分训练和K折交叉验证训练) 目录 模型训练评估中常用的两种方法代码实现 T1.留一法一次性切分训练 T2.K折交叉验证训 模型训练评估中 ...
- 【数据结构】链表:带头双向循环链表的增删查改
本篇要分享的内容是带头双向链表,以下为本片目录 目录 一.链表的所有结构 二.带头双向链表 2.1尾部插入 2.2哨兵位的初始化 2.3头部插入 2.4 打印链表 2.5尾部删除 2.6头部删除 2. ...
- 链表2--JZ25复杂链表的复制JZ36两个链表的第一个公共结点JZ55链表中环的入口结点JZ56删除链表中重复的结点
JZ25复杂链表的复制 >>点击此链接 JZ36两个链表的第一个公共结点 题目描述 输入两个无环的单链表,找出它们的第一个公共结点.(注意因为传入数据是链表,所以错误测试数据的提示是用其他 ...
最新文章
- 区分json与jsonp
- 做了这么久SEO优化,想必你很了解“网页快照”!
- 移动端事件 、zepto移动端事件
- css中对position的几种定位方式的最佳诠释
- php adodb smarty,smarty+adodb+部分自定义类的php开发模式
- 在vc2005中使用MoveWindow()调整控件大小,不能及时刷新,在vc6中则可以
- 「MacOS」无法打开***,因为无法验证开发者。
- MySQL了content函数_MySql字符串函数使用技巧
- html插入javascript变量,javascript如何引用变量?
- 将Windows MyEclipse的web项目移植到Debian下
- WinCE下监视设备插拔的参考代码
- linux网络发包性能优化
- andriod socket开发问题小结
- 【生信进阶练习1000days】day13-GEOquery
- php h5 调用摄像头_怎样使用H5调用摄像头
- 搜索引擎提交入口,导航站登陆入口大全
- [图像处理-1]:颜色中英文对照表 颜色名字 色彩名称
- 哈利波特分院考试(HP)
- win7原版iso_【JUJUMAO_MSDN系统】Windows 10 1903 64位 五版合一 原版ISO镜像
- 常见的协议的协议号及端口
热门文章
- 人物素描如何把握尺寸大小_素描fu复制粘贴位置大小
- crypto-js 前端DES加密/解密、生成秘钥 详解
- 收购完剩余股份 Monster全吞中华英才网
- 数学黑洞(一)令人拍案叫绝的卡布列克常数
- 现有的几个Unity热更新方案该如何选择,各自的优缺点是什么?
- Windows Server 2008 R2版本区分
- Floyd算法求无向图最小环
- 求无向图最小环算法-floyd
- html测试题英语,北大PKU-GATE考试真题-题库
- python os.path.split_python 中的split()函数和os.path.split()函数