补充了每个算法的基本思想,并且画了思路图,源代码都经过调试成功

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;
}

(不带头结点的)单链表增删查改,逆置单链表(两种方法),求两个单链表的第一个公共结点,合并两个单链表,单循环链表中判断第一个入环点,约瑟夫环相关推荐

  1. 单链表反转(逆置)——(四种方法实现)

    链表逆置就是把最后一个数据提到最前面,倒数第二个放到第二个--依次类推,直到第一个到最后一个. 由于链表没有下标,所以不能借助下标来实行数据的逆置,要靠空间的转移来完成链表的逆置,这里采用没有头节点的 ...

  2. C++ 链表 增删查改

    #if 1 #include<algorithm> #include<iostream> #include<vector> using namespace std; ...

  3. 约瑟夫环 java_约瑟夫环Java实现

    /** * 约瑟夫问题 * 设编号为 1,2,- n 的 n 个人围坐一圈, * 约定编号为 k(1<=k<=n)的人从 1 开始报数, * 数到 m 的那个人出列, * 它的下一位又从 ...

  4. 用C语言编写约瑟夫环程序,约瑟夫环C语言,请高手检查我的程序

    /*TC2编译通过*//*测试了几组数据,没有发现问题*//*如果有问题,再M我*/#include typedef struct Cnode {int data; int password; str ...

  5. 数据结构之单链表的增删查改等操作画图详解

    单链表 文章目录 单链表 链表的概念及其结构 概念 结构 链表的实现 开辟一个新结点 链表的销毁 打印链表 单链表的尾插 单链表的头插 单链表的头删 单链表的尾删 找到单链表中的一个结点 在pos位置 ...

  6. js删除指定html及子标签,js中如何删除某个元素下面的所有子元素?(两种方法)...

    js中如何删除某个元素下面的所有子元素?(两种方法) 一.总结 方法一:通过元素的innerHTML属性 元素element.innerHTML=""; 方法二:通过元素的remo ...

  7. ML:模型训练/模型评估中常用的两种方法代码实现(留一法一次性切分训练和K折交叉验证训练)

    ML:模型训练/模型评估中常用的两种方法代码实现(留一法一次性切分训练和K折交叉验证训练) 目录 模型训练评估中常用的两种方法代码实现 T1.留一法一次性切分训练 T2.K折交叉验证训 模型训练评估中 ...

  8. 【数据结构】链表:带头双向循环链表的增删查改

    本篇要分享的内容是带头双向链表,以下为本片目录 目录 一.链表的所有结构 二.带头双向链表 2.1尾部插入 2.2哨兵位的初始化 2.3头部插入 2.4 打印链表 2.5尾部删除 2.6头部删除 2. ...

  9. 链表2--JZ25复杂链表的复制JZ36两个链表的第一个公共结点JZ55链表中环的入口结点JZ56删除链表中重复的结点

    JZ25复杂链表的复制 >>点击此链接 JZ36两个链表的第一个公共结点 题目描述 输入两个无环的单链表,找出它们的第一个公共结点.(注意因为传入数据是链表,所以错误测试数据的提示是用其他 ...

最新文章

  1. 区分json与jsonp
  2. 做了这么久SEO优化,想必你很了解“网页快照”!
  3. 移动端事件 、zepto移动端事件
  4. css中对position的几种定位方式的最佳诠释
  5. php adodb smarty,smarty+adodb+部分自定义类的php开发模式
  6. 在vc2005中使用MoveWindow()调整控件大小,不能及时刷新,在vc6中则可以
  7. 「MacOS」无法打开***,因为无法验证开发者。
  8. MySQL了content函数_MySql字符串函数使用技巧
  9. html插入javascript变量,javascript如何引用变量?
  10. 将Windows MyEclipse的web项目移植到Debian下
  11. WinCE下监视设备插拔的参考代码
  12. linux网络发包性能优化
  13. andriod socket开发问题小结
  14. 【生信进阶练习1000days】day13-GEOquery
  15. php h5 调用摄像头_怎样使用H5调用摄像头
  16. 搜索引擎提交入口,导航站登陆入口大全
  17. [图像处理-1]:颜色中英文对照表 颜色名字 色彩名称
  18. 哈利波特分院考试(HP)
  19. win7原版iso_【JUJUMAO_MSDN系统】Windows 10 1903 64位 五版合一 原版ISO镜像
  20. 常见的协议的协议号及端口

热门文章

  1. 人物素描如何把握尺寸大小_素描fu复制粘贴位置大小
  2. crypto-js 前端DES加密/解密、生成秘钥 详解
  3. 收购完剩余股份 Monster全吞中华英才网
  4. 数学黑洞(一)令人拍案叫绝的卡布列克常数
  5. 现有的几个Unity热更新方案该如何选择,各自的优缺点是什么?
  6. Windows Server 2008 R2版本区分
  7. Floyd算法求无向图最小环
  8. 求无向图最小环算法-floyd
  9. html测试题英语,北大PKU-GATE考试真题-题库
  10. python os.path.split_python 中的split()函数和os.path.split()函数