iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言单双线性及循环链表怎么实现
  • 783
分享到

C语言单双线性及循环链表怎么实现

2023-07-05 16:07:09 783人浏览 薄情痞子
摘要

今天小编给大家分享一下C语言单双线性及循环链表怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。链表思维顺序存储结构Op

今天小编给大家分享一下C语言单双线性及循环链表怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

链表思维

顺序存储结构

Operation
InitList(*L):初始化操作,简历一个空的线性表L
ListEmpty(L):判断线性表是否为空表,若线性表为空返回true,否则返回false
ClearList(*L):将线性表清空
GetElem(L,i,*e):将线性表L中的第i个位置返回给e
LocatElem(L,e):在线性表L中查找与给定值e相等的元素,如果查找成功,返回该元素在表中序号表示成功,否则,返回0表示失败
ListInsert(*L,i,e):在线性表L中第i个位置插入元素e
ListDelete(*L,i,*e):删除线性表L中的第i个位置的元素,并用e返回其值
ListLength(L):返回线性表L的元素个数

单链表

线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以存在内存中未被占用的任意位置。
比起顺序存储结构每个数据元素只需要存储一个位置就可以了。
现在链式存储结构中,除了要存储数据元素信息外,还要存储它的后继元素的存储地址(指针)
我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称为指针。这两部分信息组成数据元素称为存储映像,称为结点(node)。
n个结点链接成一个链表,即为线性表(a1,a2,a3, …., an)的链式存储结构。
因为此链表的每个结点中只包含一个指针域,所以叫做单链表。

单链表存储结构

C语言单双线性及循环链表怎么实现

 获得链表第i个数据的算法思路:

  • 声明一个结点p指向链表第一个结点,初始化从1开始

  • 当j<i时,就遍历链表,让p的指针向后移动,不断指向一下结点,j+1;

  • 若到链表末尾p为空,则说明第i个元素不存在;

  • 否则查找成功,返回结点p的数据。

 单链表的读取
  • 通俗易懂就是从头开始找,直到第i个元素为止。

  • 由于这个算法的时间复杂度取决于i的位置,当i=1时,则不需要遍历,而i=n时则遍历n-1次才可以。因此最坏情况的时间复杂度为O(n)。

  • 由于单链表的结构中没有定义表长,所以不能实现知道要循环多少次,因此也就不方便使用for控制循环。

  • 其核心思想叫做“工作指针后移”,这其实也是很多算法的常用技术。

单链表的插入

C语言单双线性及循环链表怎么实现

 看图发现我们插入结点不需要向顺序存储一样全部更改,只需要让s -> next和p -> next发生一点指向改变:

  • s -> next = p-> next

  • p -> next = s

如图:

C语言单双线性及循环链表怎么实现

单链表第i个数据插入结点的算法思路:

声明一结点p指向链表头结点,初始化j从1开始;-当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1;
2.若到链表末尾p为空,则说明第i个元素不存在;
3.否则查找成功,在系统中生成一个空结点S;
4.将数据元素e赋值给s->data;
5.单链表的插入刚才两个标准语句;
6.返回成功

  • (表示类型)malloc(sizeof(表示长度))开辟一个空间

 单链表的删除

C语言单双线性及循环链表怎么实现

假设元素a2的结点为q,要实现结点q删除单链表的操作,其实就是将它的前继结点的指针绕过指向后面。我们要做的就是上一步
可以写成 p -> next = p ->next -> next
也可以使用
q = p -> next;p -> next = q -> next

单链表第i个数据删除结点的算法思路:

  • 声明结点p指向链表第一个结点,初始化j=1;

  • 当j < i时,就遍历链表,让P的指针向后移动,不断指向下一个结点,j累加1;

  • 一若到链表末尾p为空,则说明第i个元素不存在;

  • 否则查找成功,将欲删除结点p->next赋值给q;

  • 单链表的删除标准语句p -> next = q -> next ;

  • 将q结点中的数据赋值给e,作为返回;

  • 释放q结点。free(q)

 单链表的整表创建

创建单链表的过程是一个动态生成链表的过程,从“空表“的初始状态起,依次建立各元素结点并逐个插入链表。

所以单链表整表创建的算法思路如下:

  • 声明一结点p和计数器变量i;

  • 初始化一空链表L;

  • 让L的头结点的指针指向NULL,即建立一个带头结点的单链表;

  • 循环实现后继结点的赋值和插入。

 头插法建立单链表

头插法从一个空表开始,生成新结点,读取数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头上,直到结束为止。

简单来说,就是把新加进的元素放在表头后的第个位置:

  • 先让新节点的next指向头节点之后

  • 然后让表头的next指向新节点

 嗯,用现实环境模拟的话就是插队的方法,始终让新结点插在第一的位置。

尾插法建立单链表
单链表的整表删除
  • 声明结点p和q;

  • 将第一个结点赋值给p,下一结点赋值给q;

  • 循环执行释放p和将q赋值给p的操作;

#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0typedef int Status;Status ClearList(LinkList *L){LinKList p,q;p = (*L) -> next;while(p){q = p -> next;free(p);p = q;}(*L) -> next = NULL;return OK}//这段算法代码里,常见的错误就是有同学会觉得q变量没有存在的必要,只需要在循环体内直接写自由(P);p=p->下一步;即可?//可这个世上没有无缘无故的爱,这样做会带来什么问题呢?//要知道p是一个结点,它除了有数据域,还有指针域.当我们做自由(P);时候,其实是对它整个结点进行删除和内存释放的工作.而我们整表删除是需要一个个结点删除的,所以我们就需要q来记载p的下一个结点.
 单链表实例
#include <stdio.h>#include <stdlib.h>struct singleList{int data;struct singleList *next;};//创建一个表struct singleList*createList(){//指针变成结构体变量  struct singleList *headNode = (struct singleList *)malloc(sizeof(struct singleList));headNode -> next = NULL; //差异化处理,充当表头 return headNode; }//创建结点:  战门创建新的结点//int datastruct singleList* creatNode(int data) {struct singleList* newNode = (struct singleList *)malloc(sizeof(struct singleList));newNode -> data = data;newNode -> next = NULL;return newNode;}void insertNodeByHead(struct singleList *headNoed,int data){ struct singleList *newNode = creatNode(data); newNode -> next = headNoed -> next; headNoed -> next = newNode;}void printList(struct singleList* headNode){//因为第一个结点就是表头,所以 里面没有数据,要从第二个打印struct singleList *pMove = headNode -> next;while (pMove) {printf("%d -> ",pMove -> data);pMove = pMove -> next;}printf("\n");}int main(){struct singleList*list =createList();insertNodeByHead(list,1);insertNodeByHead(list,2);insertNodeByHead(list,3);printList(list);system("pause");return 0;}
单链表学生系统简单实例

此处使用c++语法,请自行切换

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>struct student {char name[20];int age;int num;};struct singleList {//int data;struct student data;struct singleList* next;};//创建一个表struct singleList* createList() {//指针变成结构体变量  struct singleList* headNode = (struct singleList*)malloc(sizeof(struct singleList));headNode->next = NULL; //差异化处理,充当表头 return headNode;}//创建结点:  战门创建新的结点//int datastruct singleList* creatNode(struct student data) {struct singleList* newNode = (struct singleList*)malloc(sizeof(struct singleList));newNode->data = data;newNode->next = NULL;return newNode;}void insertNodeByHead(struct singleList* headNoed, struct student data) {struct singleList* newNode = creatNode(data);newNode->next = headNoed->next;headNoed->next = newNode;}void printList(struct singleList* headNode) {//因为第一个结点就是表头,所以 里面没有数据,要从第二个打印struct singleList* pMove = headNode->next;printf("请录入信息:姓名\t年龄\t编号\n");while (pMove) {printf("%s\t%d\t%d\n ", pMove->data.name, pMove->data.age, pMove->data.num);//struct student data//printf("%d -> ",pMove -> data);pMove = pMove->next;}printf("\n");}//增删查改//void saveInfoToFile() //菜单void printMenu() {printf("---------------------\n");printf("\t\to.退出信息\n");printf("\t\t1.录入信息\n");printf("\t\t2.显示信息\n");printf("---------------------\n");}//按键处理 struct singleList* list = createList();void keyDown() {int choice = 0;scanf("%d", &choice);struct student tempDate;switch(choice){case 0:printf("正常退出\n");system("pause");break;case 1:printf("请输入学生姓名年龄编号");scanf("%s %d %d", tempDate.name, &tempDate.age, &tempDate.num);insertNodeByHead(list, tempDate);break;case 2:printList(list);break;};}int main() {//struct singleList*list =createList();//insertNodeByHead(list,1);//insertNodeByHead(list,2);//insertNodeByHead(list,3);//printList(list);while (1) {printMenu();keyDown();system("pause");system("cls");}system("pause");return 0;};//1.先写链表,先写数据结构//2.修改data//3.系统应用开发

双向链表

C语言单双线性及循环链表怎么实现

双链表 

  • main.h

#pragma once#include <stdio.h>#include <stdlib.h>//双向链表结构体typedef struct doubleLink {    char data;//记录节点所在的行和列    struct doubleLink* pre;//指向前驱节点的指针    struct doubleLink* next;//指向后续节点的指针};//初始化双链表struct doubleLink* initDoubleLink();//查询struct doubleLink* selectDoubleLink(struct doubleLink* p, int site);//插入struct doubleLink* insertDoubleLink(struct doubleLink* p, int site, int value);//删除struct doubleLink* deleteDoubleLink(struct doubleLink* p, int site);//修改struct doubleLink* updateDoubleLink(struct doubleLink* p, int site, int value);//打印void display(doubleLink* head);
  • main.cpp

#include "main.h"int main() {printf("双链表\n");struct doubleLink* doubleLink = NULL;display(doubleLink);doubleLink = initDoubleLink();display(doubleLink);insertDoubleLink(doubleLink, 2, 100);display(doubleLink);deleteDoubleLink(doubleLink, 2);display(doubleLink);updateDoubleLink(doubleLink, 2, 100);display(doubleLink);return 0;}
  • doubleLink.cpp

#include "main.h"struct doubleLink* initDoubleLink() {doubleLink* headNode = NULL;doubleLink* temp = NULL;headNode = (doubleLink*)malloc(sizeof(doubleLink));headNode->data = 0;headNode->next = NULL;headNode->pre = NULL;temp = headNode;for (int i = 1; i <= 4; i++){doubleLink* a = (doubleLink*)malloc(sizeof(doubleLink));a->data = i;a->next = NULL;a->pre = temp;temp->next = a;temp = temp->next;}return headNode;}struct doubleLink* insertDoubleLink(struct doubleLink* p, int site, int value) {doubleLink* body = NULL;body = p;doubleLink* temp = NULL;temp = (doubleLink*)malloc(sizeof(doubleLink));temp->data = value;temp->pre = NULL;temp->next = NULL;body = selectDoubleLink(p, site);temp->next = body->next;temp->pre = body;body->next = temp;return p;}struct doubleLink* deleteDoubleLink(struct doubleLink* p, int site) {doubleLink* body = NULL;body = p;body = selectDoubleLink(p, site);body->next = body->next->next;body->next->pre = body;return p;}struct doubleLink* updateDoubleLink(struct doubleLink* p, int site,int value) {doubleLink* body = NULL;body = p;body = selectDoubleLink(p, site);body->next->data = value;return p;}struct doubleLink* selectDoubleLink(struct doubleLink* p, int site) {doubleLink* temp = p;int i;for (i = 1; i < site; i++){if (temp == NULL) {printf("查询失败");return p;}temp = temp->next;}return temp;}void display(doubleLink* head) {doubleLink* temp = head;while (temp) {if (temp->next == NULL) {printf("%d\n", temp->data);}else {printf("%d->", temp->data);}temp = temp->next;}}
 双向链表实现贪吃蛇

贪吃蛇实例展示:

C语言单双线性及循环链表怎么实现

思想结构分析:

我们知道,双向链表中各个节点的标准构成是一个数据域和 2 个指针域,但对于实现贪吃蛇游戏来说,由于各个节点的位置是随贪吃蛇的移动而变化的,因此链表中的各节点还需要随时进行定位。
在一个二维画面中,定义一个节点的位置,至少需要所在的行号和列号这 2 个数据。由此,我们可以得出构成贪吃蛇的双向链表中各节点的构成:

//创建表示蛇各个节点的结构体typedef struct SnakeNode {    int x, y;//记录节点所在的行和列    struct SnakeNode *pre;//指向前驱节点的指针    struct SnakeNode *next;//指向后续节点的指针}Node, *pNode;

贪吃蛇的移动,本质上就是对链表中各个节点的重新定位。换句话说,除非贪吃蛇吃到食物,否则无论怎样移动,都不会对双向链表的整个结构(节点数)产生影响,唯一受影响的就只是各个节点中 (x,y) 这对定位数据。

由此,我们可以试着设计出实现贪吃蛇移动的功能函数,本节所用的实现思想分为 2 步:

  • 从蛇尾(双向链表尾节点)开始,移动向前遍历,过程中依次将当前节点的 (x,y) 修改为前驱节点的 (x,y),由此可实现整个蛇身(除首元节点外的其它所有节点)的向前移动;

  • 接收用户输入的移动指令,根据用户指示贪吃蛇向左、向右、向上还是向下移动,首元节点中的 (x,y) 分别做 x-1、x+1、y-1 和 y+1 运算。

 如下所示,move() 函数就实现了贪吃蛇的移动:

//贪吃蛇移动的过程,即链表中所有节点从尾结点开始逐个向前移动一个位置bool Move(pNode pHead, char key) {    bool game_over = false;    pNode pt = pTail;    while (pt != pHead) { // 每个节点依次向前完成蛇的移动        pt->x = pt->pre->x;        pt->y = pt->pre->y;        pt = pt->pre;    }    switch (key) {        case'd': {            pHead->x += 1;            if (pHead->x >= ROW)                game_over = true;            break;        }        case'a': {            pHead->x -= 1;            if (pHead->x < 0)                game_over = true;            break;        }        case's': {            pHead->y += 1;            if (pHead->y >= COL)                game_over = true;            break;        }        case'w': {            pHead->y -= 1;            if (pHead->y < 0)                game_over = true;;            break;        }    }    if (SnakeDeath(pHead))        game_over = true;    return game_over;}

注意,此段代码中还调用了 SnakeDeath() 函数,此函数用于判断贪吃蛇移动时是否撞墙、撞自身,如果是则游戏结束。

当贪吃蛇吃到食物时,贪吃蛇需要增加一截,其本质也就是双向链表增加一个节点。前面章节中,已经详细介绍了如何在双向链表中增加一个节点,因此实现这个功能唯一的难点在于:如何为该节点初始化 (x,y)?
本节所设计的贪吃蛇游戏,针对此问题,提供了最简单的解决方案,就是不对新节点 x 和 y 做初始化。要知道,贪吃蛇是时刻移动的,而在上面的 move() 函数中,会时刻修正贪吃蛇每个节点的位置,因此当为双向链表添加新节点后,只要贪吃蛇移动一步,新节点的位置就会自行更正。
也就是说,贪吃蛇吃到食物的实现,就仅是给双向链表添加一个新节点。如下即为实现此功能的代码:

//创建表示食物的结构体,其中只需要记录其所在的行和列typedef struct Food {    int x;    int y;}Food, *pFood;//吃食物,等同于链表中新增一个节点pNode EatFood(pNode pHead, pFood pFood) {    pNode p_add = NULL, pt = NULL;    if (pFood->x == pHead->x&&pFood->y == pHead->y) {        p_add = (pNode)malloc(sizeof(Node));        score++;        pTail->next = p_add;        p_add->pre = pTail;        p_add->next = NULL;        pTail = p_add;        // 检查食物是否出现在蛇身的位置上        do {            *pFood = CreateFood();        } while (FoodInSnake(pHead, pFood));    }    return pHead;}

其中,Food 结构体用来表示食物,其内部仅包含能够定位食物位置的 (x,y) 即可。另外,此段代码中,还调用了 FoodeInSnake() 函数,由于食物的位置是随机的,因此极有可能会和贪吃蛇重合,所以此函数的功能就是:如果重合,就重新生成食物。

FoodInSnake() 函数的实现很简单,这里不再赘述:

//判断食物的出现位置是否和蛇身重合bool FoodInSnake(pNode pHead, pFood pFood) {    pNode pt = NULL;    for (pt = pHead; pt != NULL; pt = pt->next) {        if (pFood->x == pt->x&&pFood->y == pt->y)            return true;    }    return false;}

贪吃蛇游戏界面的显示,最简单的制作方法就是:贪吃蛇每移动一次,都清除屏幕并重新生成一次。这样实现的问题在于,如果贪吃蛇的移动速度过快,则整个界面在渲染的同时,会掺杂着光标,并且屏幕界面会频繁闪动。

因此,在渲染界面时,有必要将光标隐藏起来,这需要用到<windows.h>头文件,实现代码如下:

// 隐藏光标void Gotoxy(int x, int y) {    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);    COORD pos;    pos.X = x;    pos.Y = y;    SetConsoleCursorPosition(handle, pos);}void HideCursor() {    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);}

同时,为了给整个界面渲染上颜色,也需要引入<windows.h>头文件,并使用如下函数:

void color(int m) {    HANDLE consolehend;    consolehend = GetStdHandle(STD_OUTPUT_HANDLE);    SetConsoleTextAttribute(consolehend, m);}

需要注意的一点是,由此结束后,一定要手动释放双向链表占用的堆空间:

//退出游戏前,手动销毁链表中各个节点void ExitGame(pNode *pHead){    pNode p_delete = NULL, p_head = NULL;    while (*pHead != NULL) {        p_head = (*pHead)->next;        if (p_head != NULL)            p_head->pre = NULL;        p_delete = *pHead;        free(p_delete);        p_delete = NULL;        *pHead = p_head;    }}

循环链表

无论是静态链表还是动态链表,有时在解决具体问题时,需要我们对其结构进行稍微地调整。比如,可以把链表的两头连接,使其成为了一个环状链表,通常称为循环链表。

只需要将表中最后一个结点的指针指向头结点,链表就能成环儿

C语言单双线性及循环链表怎么实现

需要注意的是,虽然循环链表成环状,但本质上还是链表,因此在循环链表中,依然能够找到头指针和首元节点等。循环链表和普通链表相比,唯一的不同就是循环链表首尾相连,其他都完全一样。

循环链表实现约瑟夫环

约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 n 个人(分别用编号 1,2,3,&hellip;,n 表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 开始,还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,直到圆桌上剩余一个人。

如图 2 所示,假设此时圆周周围有 5 个人,要求从编号为 3 的人开始顺时针数数,数到 2 的那个人出列:

C语言单双线性及循环链表怎么实现

实践项目之俄罗斯轮盘赌小游戏

俄罗斯轮盘是一个残忍的游戏,具体规则为:游戏的道具是一把左轮手枪,其规则也很简单:在左轮手枪中的 6 个弹槽中随意放入一颗或者多颗子弹,在任意旋转转轮之后,关上转轮。游戏的参加者轮流把手枪对着自己,扣动扳机:中枪或是怯场,即为输的一方;坚持到最后的即为胜者。
本节实践项目同轮盘赌类似,游戏规则:n 个参加者排成一个环,每次由主持向左轮手枪中装一颗子弹,并随机转动关上转轮,游戏从第一个人开始,轮流拿枪;中枪者退出赌桌,退出者的下一个人作为第一人开始下一轮游戏。直至最后剩余一个人,即为胜者。要求:模拟轮盘赌的游戏规则,找到游戏的最终胜者。

俄罗斯轮盘设计思路

决类似的问题,使用线性表的顺序存储结构和链式存储结构都能实现,根据游戏规则,在使用链式存储结构时只需使用循环链表即可轻松解决问题。

顺序存储结构模拟轮盘
#include <stdio.h>#include <stdlib.h>#include <time.h>//链表节点单元 typedef struct GameMan{    int Man;    struct GameMan * next;}GameMan;//建立游戏人员循环链表void InitGameManLine(GameMan **GameMans,int PersonNum){    *GameMans=(GameMan *)malloc(sizeof(GameMan));//头指针指向首元节点     //节点初始化 (*GameMans)->next=NULL;    (*GameMans)->Man=1;    GameMan *tail=*GameMans;//指向链表尾     for (int i=2;i<=PersonNum;i++){        GameMan *newnode=(GameMan *)malloc(sizeof(GameMan));//申请新节点         //节点初始化 newnode->next=NULL;        newnode->Man=i;        tail->next=newnode;//将新节点链接到链表尾         tail=tail->next;//移动tail到尾指针     }    tail->next=*GameMans;//将链表成环}//输出链表中所有游戏成员 void display(GameMan *GameMans){    GameMan *temp=GameMans;    while (temp->next!=GameMans){        printf("%d ",temp->Man);        temp=temp->next;    }    printf("%d\n\n",temp->Man);}int main() {    GameMan *GameMans=NULL;//游戏成员链表头指针int round=1;     int PersonNum;int BulletPos;//srand((int)time(0));//使用当前时间作为rand()函数的随机数的种子 srand((unsigned) time(NULL));printf("请输入本次游戏人数(<100): ");    scanf("%d",&PersonNum);    printf("\n为编号为 1-%d 的游戏人员分配位置!\n\n",PersonNum);    InitGameManLine(&GameMans,PersonNum);    GameMan* lineNext=GameMans;//用于记录每轮开始的位置    //仅当链表中只含有一个结点时,即头结点时,退出循环    while(GameMans->next!=GameMans){        BulletPos=rand()%6+1;        printf("第 %d 轮游戏,从编号为 %d 的人开始,枪在第 %d 次扣动扳机时会响!\n\n",round,lineNext->Man,BulletPos);        GameMan *temp=lineNext;        //遍历循环链表,找到将要删除结点的上一个结点        for (int i=1;i<BulletPos-1;i++){            temp=temp->next;        }        //如果子弹位置BulletPos==1,则要找到当前节点的上一节点         if(BulletPos==1){        while(temp->next!=lineNext){        temp=temp->next;        }        }         printf("编号为 %d 的赌徒退出赌博,剩余赌徒编号依次为:",temp->next->Man);        //将要删除结点从链表中删除,并释放其占用空间GameMan * del=temp->next;//记录删除节点         temp->next=temp->next->next;//从链表中移除该节点         if(del==GameMans)GameMans=GameMans->next;//如果删除的是头节点,将头节点的下一节点作为头节点         free(del);//释放del节点         display(GameMans);        //下一轮开始的位置        lineNext=temp->next;        round++;//回合次数加一    }    printf("最终胜利的游戏人员编号是:%d \n\n",GameMans->Man);    return 0;}

运行结果示例:

C语言单双线性及循环链表怎么实现

 链表实现俄罗斯轮盘
#include <stdio.h>#include <stdlib.h>#include <time.h>//链表节点单元 typedef struct GameMan{    int Man;    struct GameMan * next;}GameMan;//建立游戏人员循环链表void InitGameManLine(GameMan **GameMans,int PersonNum){    *GameMans=(GameMan *)malloc(sizeof(GameMan));//头指针指向首元节点     //节点初始化 (*GameMans)->next=NULL;    (*GameMans)->Man=1;    GameMan *tail=*GameMans;//指向链表尾     for (int i=2;i<=PersonNum;i++){        GameMan *newnode=(GameMan *)malloc(sizeof(GameMan));//申请新节点         //节点初始化 newnode->next=NULL;        newnode->Man=i;        tail->next=newnode;//将新节点链接到链表尾         tail=tail->next;//移动tail到尾指针     }    tail->next=*GameMans;//将链表成环}//输出链表中所有游戏成员 void display(GameMan *GameMans){    GameMan *temp=GameMans;    while (temp->next!=GameMans){        printf("%d ",temp->Man);        temp=temp->next;    }    printf("%d\n\n",temp->Man);}int main() {    GameMan *GameMans=NULL;//游戏成员链表头指针int round=1;     int PersonNum;int BulletPos;//srand((int)time(0));//使用当前时间作为rand()函数的随机数的种子 srand((unsigned) time(NULL));printf("请输入本次游戏人数(<100): ");    scanf("%d",&PersonNum);    printf("\n为编号为 1-%d 的游戏人员分配位置!\n\n",PersonNum);    InitGameManLine(&GameMans,PersonNum);    GameMan* lineNext=GameMans;//用于记录每轮开始的位置    //仅当链表中只含有一个结点时,即头结点时,退出循环    while(GameMans->next!=GameMans){        BulletPos=rand()%6+1;        printf("第 %d 轮游戏,从编号为 %d 的人开始,枪在第 %d 次扣动扳机时会响!\n\n",round,lineNext->Man,BulletPos);        GameMan *temp=lineNext;        //遍历循环链表,找到将要删除结点的上一个结点        for (int i=1;i<BulletPos-1;i++){            temp=temp->next;        }        //如果子弹位置BulletPos==1,则要找到当前节点的上一节点         if(BulletPos==1){        while(temp->next!=lineNext){        temp=temp->next;        }        }         printf("编号为 %d 的赌徒退出赌博,剩余赌徒编号依次为:",temp->next->Man);        //将要删除结点从链表中删除,并释放其占用空间GameMan * del=temp->next;//记录删除节点         temp->next=temp->next->next;//从链表中移除该节点         if(del==GameMans)GameMans=GameMans->next;//如果删除的是头节点,将头节点的下一节点作为头节点         free(del);//释放del节点         display(GameMans);        //下一轮开始的位置        lineNext=temp->next;        round++;//回合次数加一    }    printf("最终胜利的游戏人员编号是:%d \n\n",GameMans->Man);    return 0;}

C语言单双线性及循环链表怎么实现

以上就是“C语言单双线性及循环链表怎么实现”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网其他教程频道。

--结束END--

本文标题: C语言单双线性及循环链表怎么实现

本文链接: https://www.lsjlt.com/news/353327.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言单双线性及循环链表怎么实现
    今天小编给大家分享一下C语言单双线性及循环链表怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。链表思维顺序存储结构Op...
    99+
    2023-07-05
  • C语言单双线性及循环链表与实例
    目录链表思维顺序存储结构单链表单链表存储结构 单链表的读取单链表的插入 单链表的删除 单链表的整表创建 头插法建立单链表尾插法建立单链表单链表...
    99+
    2023-03-24
    C语言单双链表 C语言循环链表
  • C语言怎么实现循环双链表
    这篇文章主要介绍“C语言怎么实现循环双链表”,在日常操作中,相信很多人在C语言怎么实现循环双链表问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言怎么实现循环双链表”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-25
  • C语言实现循环双链表
    本文实例为大家分享了C语言实现循环双链表的具体代码,供大家参考,具体内容如下 #include<stdio.h> #include<stdlib.h> #...
    99+
    2022-11-12
  • C语言怎么实现线性表中的带头双向循环链表
    这篇文章主要介绍了C语言怎么实现线性表中的带头双向循环链表的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言怎么实现线性表中的带头双向循环链表文章都会有所收获,下面我们一起来看看吧。一、本章重点带头双向循环链...
    99+
    2023-06-29
  • C语言怎么实现带头双向循环链表
    本篇内容主要讲解“C语言怎么实现带头双向循环链表”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言怎么实现带头双向循环链表”吧!创建链表存储结构我们需要创建一个结构体来存储一个链表结点的相关信...
    99+
    2023-06-30
  • C语言带头双向循环链表怎么实现
    这篇“C语言带头双向循环链表怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言带头双向循环链表怎么实现”文章吧。带...
    99+
    2023-06-30
  • C语言如何实现双向链表和双向循环链表
    本文小编为大家详细介绍“C语言如何实现双向链表和双向循环链表”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言如何实现双向链表和双向循环链表”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。双向链表和双向循环链表...
    99+
    2023-06-16
  • C语言实现带头双向循环链表
    目录前言1. 创建结构体2.malloc新节点3.创建哨兵位节点4.尾插5.打印6.尾删7.头插8.在指定位置pos的前面进行插入9. 删除指定位置pos节点10.销毁链表前言 在...
    99+
    2022-11-13
  • 详解C语言中双向循环链表的实现
    目录实现细节辅助理解图具体实现代码1、对链表进行初始化2、任意位置前的插入3、任意位置的删除4、头插和尾删完整代码头文件具体函数测试实现细节 1、带一个哨兵位(哨兵节点,初始节点,不...
    99+
    2022-11-13
  • C语言如何实现带头双向循环链表
    这篇文章主要介绍了C语言如何实现带头双向循环链表,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前言在实际生活中最常用的就是这两种链表。无头单向非循环链表。和带头双向循环链表。...
    99+
    2023-06-29
  • C语言用循环单链表实现约瑟夫环
    用循环单链表实现约瑟夫环(c语言),供大家参考,具体内容如下 源代码如下,采用Dev编译通过,成功运行,默认数到三出局。 主函数: main.c文件 #include <s...
    99+
    2022-11-12
  • C语言实现带头双向循环链表的接口
    本文实例为大家分享了C语言实现带头双向循环链表的接口,供大家参考,具体内容如下 各函数功能如下 申请空间 ListNode* BuyListNode(LTDataType x) ...
    99+
    2022-11-12
  • C语言超详细介绍与实现线性表中的带头双向循环链表
    目录一、本章重点二、带头双向循环链表介绍2.1什么是带头双向循环链表?2.2最常用的两种链表结构三、带头双向循环链表常用接口实现 3.1结构体创建3.2带头双向循环链表的初始化 3....
    99+
    2022-11-13
  • C语言双链表怎么实现
    本篇内容介绍了“C语言双链表怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!定义链表是通过一组任意的存储单元来存储线性表中的数据元素,...
    99+
    2023-06-29
  • C语言怎么实现线性动态单向链表
    本篇内容主要讲解“C语言怎么实现线性动态单向链表”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言怎么实现线性动态单向链表”吧!什么是链表链表是数据结构里面的一种,线性链表是链表的一种,线性链...
    99+
    2023-06-30
  • C语言详解如何实现带头双向循环链表
    目录创建链表存储结构创建结点链表的初始化双向链表的打印双向链表尾插双向链表尾删双向链表头插双向链表头删双向链表查找双向链表pos前插入结点双向链表删除pos位置的结点双向链表的销毁顺...
    99+
    2022-11-13
  • C语言数据结构中双向带头循环链表怎么实现
    这篇文章主要讲解了“C语言数据结构中双向带头循环链表怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言数据结构中双向带头循环链表怎么实现”吧!一、概念来画张图总体回顾下:在我们学习...
    99+
    2023-06-30
  • C语言怎么实现带头双向环形链表
    本篇内容主要讲解“C语言怎么实现带头双向环形链表”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言怎么实现带头双向环形链表”吧!双向循环链表上一次我们讲了单向无头非循环链表的实现,单向无头非循...
    99+
    2023-06-21
  • C++带头双向循环链表怎么实现
    这篇文章主要介绍“C++带头双向循环链表怎么实现”,在日常操作中,相信很多人在C++带头双向循环链表怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++带头双向循环链表怎么实现”的疑惑有所帮助!接下来...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作