数据结构之双向循环链表

来源:互联网 发布:反监听软件 编辑:程序博客网 时间:2024/05/16 05:05

[写文目的]

为了更深入的了解链表,于是在这里写出单向链表的升级版双向循环链表!

[链表介绍]

1.建立链表

首先需要定义一个结构,一般双向循环链表的结构用于存放储存在该节点的值,一个prev指针指向前一个节点,一个rnext指针指向下一个节点,对用结构代码如下:

typedef struct Node* node;struct Node{int data;node prev;node next;};
创建一个双向循环链表的代码如下

node creatList(){node L=(node)malloc(sizeof(Node));L->prev=NULL;L->next=NULL;return L;}
2.插入元素

示意图为


代码为:

void insertItem(node L,int n){node tempNode=creatList();tempNode->data=n;L->next->prev=tempNode;tempNode->next=L->next;L->next=tempNode;tempNode->prev=L;}
3.删除元素

示意图为:


代码为:

void deleteItem(node L,int n){node head=L;//保存L(相当于头结点),在循环链表这一步也可以去掉while(L->data!=n){L=L->next;}//这里默认n值在链表中存在//找到存储n的节点后node p=L;L->next->prev=L->prev;L->prev->next=L->next;free(p);L=head;}
[总结]

对于双向循环链表,我使用的测试代码为

#include<stdio.h>#include<malloc.h>typedef struct Node* node;struct Node{int data;node prev;node next;};node creatList(){node L=(node)malloc(sizeof(Node));L->prev=L;L->next=L;return L;}void insertItem(node L,int n){node tempNode=creatList();tempNode->data=n;L->next->prev=tempNode;tempNode->next=L->next;L->next=tempNode;tempNode->prev=L;}void deleteItem(node L,int n){node head=L;//保存L(相当于头结点),在循环链表这一步也可以去掉while(L->data!=n){L=L->next;}//这里默认n值在链表中存在//找到存储n的节点后node p=L;L->next->prev=L->prev;L->prev->next=L->next;free(p);L=head;}int main(){node n;n=creatList();n->data=4;insertItem(n,5);insertItem(n,8);insertItem(n,6);insertItem(n,9);deleteItem(n,8);for(int i=0;i<12;i++){printf("%d\n",n->data);n=n->next;}return 0;}


[问题提出]

对于该数据结构,我引入一个题目,便于更好的掌握双向循环链表!

题目描述:
编号为 1 - n 的 n 个人按顺时针方向围坐一圈,从第一个人开始按顺时针方向自 1 开
始报数,报到 m 时停止,在报到 m 的那个人的左右的两个人出列,从他在顺时针方向下一
个人开始重新从 1 报数,如此下去。如果还在游戏的人数少于 3 个,则游戏终止。在一行
内输出最后留下来的人编号
★数据输入
输入第一行为 T ,代表接下去有 T 组测试, 0 < T < =10
接下去 T行,每行两个数代表 n 和m,0 < n,m < =1000
★数据输出
对于每个输入,在一行内输出最后留下来的人编号,如果有两个人留下来,则用空格隔
开,并按从小到大排序。
输入示例      输出示例
3              
1 2                 1
3 1                 1
4 2                 2 4

[解题思路]

首先我们需要建立双循环链表,节点存储编号n,以及left跟right(也就相当于prev跟next)用于指向左右节点

typedef struct LinkedList* List;struct LinkedList{List right;List left;int n;};
建立循环链表,由于是1-n的顺序,所以我们是在链表尾部,对应代码为:

List creatList(int peopleNum)//传入参与游戏的人数{List mainList;List leftList;List headList;        //保存指向第一个节点的指针,后面用于返回headList=mainList=leftList=NULL;for(int i=1;i<=peopleNum;i++)//依次增加节点{leftList=(List)malloc(sizeof(LinkedList));leftList->n=i;if(mainList==NULL){ mainList=headList=leftList; //保存第一个节点}else {//在mainList后面依次增加节点mainList->left=leftList;leftList->right=mainList;mainList=leftList;}}mainList->left=headList;  //这两段代码用于首尾相连,构成循环链表headList->right=mainList;return headList;    //返回第一个节点}

查找并依次删除符合点检的节点的左右节点

void searchList(List mainList,int n,int m){while(n>2)//当目前参与游戏的人数大于2的时候进行以下的操作{int mTemp=(m%n);while(mTemp--)//找到符合删除条件的节点{mainList=mainList->left;}List p,q;//待删节点,为mainList的左节点和右节点p=mainList->right;q=mainList->left;mainList->right=p->right;p->right->left=mainList;mainList->left=q->left;q->left->right=mainList;free(p);free(q);n-=2;//删除操作完成后人数减去两个人}if(n==1) printf("%d\n",mainList->n);else printf("%d %d\n",(mainList->n)>(mainList->left->n)?(mainList->left->n):(mainList->n),\(mainList->n)<(mainList->left->n)?(mainList->left->n):(mainList->n));}
这个题目的难点就是以上的建立链表一个删除符合条件的节点两个,对应的完整代码如下:

#include<stdio.h>#include<malloc.h>typedef struct LinkedList* List;struct LinkedList{List right;List left;int n;};List creatList(int peopleNum)//传入参与游戏的人数{List mainList;List leftList;List headList;        //保存指向第一个节点的指针,后面用于返回headList=mainList=leftList=NULL;for(int i=1;i<=peopleNum;i++)//依次增加节点{leftList=(List)malloc(sizeof(LinkedList));leftList->n=i;if(mainList==NULL){ mainList=headList=leftList; //保存第一个节点}else {//在mainList后面依次增加节点mainList->left=leftList;leftList->right=mainList;mainList=leftList;}}mainList->left=headList;  //这两段代码用于首尾相连,构成循环链表headList->right=mainList;return headList;    //返回第一个节点}void searchList(List mainList,int n,int m){while(n>2)//当目前参与游戏的人数大于2的时候进行以下的操作{int mTemp=(m%n);while(mTemp--)//找到符合删除条件的节点{mainList=mainList->left;}List p,q;//待删节点,为mainList的左节点和右节点p=mainList->right;q=mainList->left;mainList->right=p->right;p->right->left=mainList;mainList->left=q->left;q->left->right=mainList;free(p);free(q);n-=2;//删除操作完成后人数减去两个人}if(n==1) printf("%d\n",mainList->n);else printf("%d %d\n",(mainList->n)>(mainList->left->n)?(mainList->left->n):(mainList->n),\(mainList->n)<(mainList->left->n)?(mainList->left->n):(mainList->n));}int main(){int m,n;int num;scanf("%d",&num);while(num--){scanf("%d%d",&n,&m);List list;list=creatList(n);searchList(list->right,n,m);}}





0 0
原创粉丝点击