单循环链表是C语言中比较常见的一种链式储存结构。
相较于普通的单链表,其特点就在于单循环链表的尾指针指向的是头结点。
即:
1.单链表
2.
单循环链表的有点就在于方便访问第一个结点,还方便访问最后一个结点。
那么,话不多说,先建立一个单循环链表:
(先给出相关的定义:PNode 、LinkList 分别表示结点和链表,DataType即int,结构体Node含有两个成员:data和next指针)
typedef int DataType;
typedef struct Node* PNode;
typedef struct Node* LinkList;
struct Node {
DataType data;
struct Node* next;
};
接下来就是建立单循环链表的函数:
ps:这样建立的单链表,会有一个空的头节点(head)。
LinkList CreateList_Tail_loop()
{
LinkList head = (LinkList)malloc(sizeof(struct Node));
PNode cur = NULL;
PNode tail = head;
DataType data;
printf("please input some Numbers:\n");
scanf_s("%d", &data);
while (data != -1)
{
cur = (struct Node*)malloc(sizeof(struct Node));
cur->data = data;
tail->next = cur;
tail = cur;
scanf_s("%d", &data);
}
tail->next = head;//尾指针指向头结点
return tail;
}
链表建立好了之后,就可以开始进行移动了~
ps: tail为已经建立好的链表
temp用来记录头结点
pre为p的前驱结点,p为用于判断的结点。
PNode Move_Odd_Even(LinkList tail)
{
PNode last = NULL, p = NULL, pre = NULL, temp = NULL;
int flag = 1;
last = tail;
temp = tail->next;
pre = tail->next;
p = (tail->next)->next;
tail->next = NULL;
while (flag)
{
if (p == tail)
{
break;
}
if ((p->data) % 2 == 0)
{
pre->next = p->next;
p->next = NULL;
last->next = p;
last = p;
p = pre->next;
}
else
{
pre = p; //记录p的前驱
p = p->next;
}
}
if (tail->data % 2 == 0)
{
pre->next = p->next;
p->next = NULL;
last->next = p;
last = p;
}
last->next = temp;
tail = last;
return tail;
}
来看全部代码与运行结果:
//实现对单循环链表中奇数和偶数结点的移动
#include<stdio.h>
#include<stdlib.h>
#include <cstddef>
typedef int DataType;
typedef struct Node* PNode;
typedef struct Node* LinkList;
struct Node {
DataType data;
struct Node* next;
};
PNode Move_Odd_Even(LinkList tail);
LinkList CreateList_Tail_loop()
{
LinkList head = (LinkList)malloc(sizeof(struct Node));
PNode cur = NULL;
PNode tail = head;
DataType data;
printf("please input some nums:\n");
scanf_s("%d", &data);
while (data != -1)
{
cur = (struct Node*)malloc(sizeof(struct Node));
cur->data = data;
tail->next = cur;
tail = cur;
scanf_s("%d", &data);
}
tail->next = head;
return tail;
}
void print(LinkList tail)
{
PNode head = tail->next;
PNode p = head->next;
while (p != head)
{
printf("%d ", p->data);
p = p->next;
}
}
void DestoryList_Link(LinkList tail)
{
PNode pre = tail->next;
PNode p = pre->next;
while (p != tail)
{
free(pre);
pre = p;
p = pre->next;
}
free(pre);
free(tail);
}
int main()
{
LinkList tail = NULL;
LinkList p = NULL;
tail = CreateList_Tail_loop();
p = Move_Odd_Even(tail);
print(p);
DestoryList_Link(tail);
return 0;
}
PNode Move_Odd_Even(LinkList tail)
{
PNode last = NULL, p = NULL, pre = NULL, temp = NULL;
int flag = 1;
last = tail;
temp = tail->next;
pre = tail->next;
p = (tail->next)->next;
tail->next = NULL;
//第一个结点的data为奇数时
while (flag)
{
if (p == tail)
{
break;
}
if ((p->data) % 2 == 0)
{
pre->next = p->next;
p->next = NULL;
last->next = p;
last = p;
p = pre->next;
}
else
{
pre = p; //记录p的前驱
p = p->next;
}
}
if (tail->data % 2 == 0)
{
pre->next = p->next;
p->next = NULL;
last->next = p;
last = p;
}
last->next = temp;
tail = last;
return tail;
}
运行结果:
刚写的单循环链表时候还是遇到了蛮多的坑,吃了一些 有无空头节点 的苦。若是题目要求写一个函数实现链表操作的某一个功能时,一定要注意题中提供的链表有无头结点!
可以将tail以及其后面几个结点的值打印出来,这样就可以知道链表的模样了。
第一次写博客,若是有哪些写错的地方,欢迎大家在评论区留言指正~