[写文目的]
为了更深入的了解链表,于是在这里写出单向链表的升级版双向循环链表!
[链表介绍]
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); } }