循环链表
#include<stdio.h>
#include<stdlib.h>
typedef struct stu
{
int data;
struct stu *next;
}node;
node *plst()
{
node *head,*tail,*p;
head=tail=p=NULL;
int x;
char f;
while(1)
{
scanf("%c",&f);
x=f-'0';
if(f=='\n')
break;
p=(node *)malloc(sizeof(node));
p->data=x;
p->next=NULL;
if(head==NULL)
{
head=tail=p;
}
else
{
node *r=head;
node *pre=NULL;
while(r)
{
if(x<r->data)
break;
else
{
pre=r;
r=r->next;
}
}
if(r==head)
{
p->next=head;
head=p;
}
else if(r==NULL)
{
tail->next=p;
tail=p;
}
else
{
pre->next=p;
p->next=r;
}
}
}
tail->next=head;//循环链表的创建
return head;
}
void print(node *A)
{
if(A)
{
node *head=A;
do
{
printf("%d",A->data);
A=A->next;
}while(A!=head);
}
printf("\n");
}//打印循环链表用do-while
node * findlast(node *A)
{
if(A)
{
node *head=A;
while(A->next!=head)
{
A=A->next;
}
return A;
}
}//找到循环链表的“尾”
node *deletall(node *A,int x)
{
if(A)
{
node *r=A;
node *pre=findlast(A);
node *tail=pre;
do
{
if(r->data==x)
{
while(A->data==x&&A>next!=A)//r等于A的情况
{
A=A->next;
tail->next=A;
r->next=NULL;
free(r);
r=A;
/*tail->next=r->next;
r->next=NULL;
free(r);
r=tail->next;*/为什么这样不可以,而且会出现段错误?
}
if(A->data==x)
{
free(A);
A=NULL;
return NULL;
}
if(r!=A)
{
pre->next=r->next;
r->next=NULL;
free(r);
r=pre->next;
}
}
else
{
pre=r;
r=r->next;
}
}while(r!=A);
}
return A;
}//删除链表所有为x的值
int main (void)
{
node *A=plst();
int x;
scanf("%d",&x);
node *B=deletall(A,x);
print(B);
/*print(deletall(A,x));*/这样也可以打印
return 0;
}
#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct node
{
ElementType data;
struct node *next;
}Node;
Node *Create_List(void)
{
Node *head,*tail,*p;
head = tail = p = NULL;
ElementType x;
while(1)
{
scanf("%d",&x);
if(x == 0)
break;
p = (Node *)malloc(sizeof(Node));
p->data = x;
p->next = NULL;
if(head == NULL)
{
head = tail = p;
tail->next = head;
}
else
{
Node *r = head;
Node *pre = tail;
do
{
if(r->data > x)
break;
else
{
pre = r;
r = r->next;
}
}while(r != head);
/*
此时结束while循环有两个条件,一个条件时r == head;
另外一个条件时r != head ,但是r ->data > x 的。
我们需要根据这两种情况去分析到底应该采用哪种插入的方式
如果是 r == head, 那么有可能是一进来满足if语句就出去了,那么
此时应该采用头插法,也有可能是遍历完了整个链表都没有找到(r == head),
那么此时应该采用尾插法
剩下的一种情况就是插入中间的情况了,采用和单链表一样的插入方式
*/
if(r != head)//插入中间
{
pre->next = p;
p->next = r;
}
else//头尾
{
if(r->data > x) //头插法
{
p->next = head;
head = p;
tail->next = head;
}
else //尾插法
{
tail->next = p;
tail = p;
tail->next = head;
}
}
}
}
return head;
}
void PrintList(Node *list)
{
if(list)//保证list不为空
{
Node *head = list;
do
{
printf("%d\t",list->data);
list = list->next;
}while(list != head);
}
printf("\n");
}
Node *find_last(Node *list)
{
if(list)
{
Node *head = list;
while(list->next != head)
list = list->next;
}
return list;
}
Node *delete_all_num(Node *list,ElementType num)
{
if(list)
{
Node *r = list;
Node *pre = find_last(list);
Node *tail = pre;
do
{
if(r->data == num)
{
/*
while 循环的前面一个条件是为了解决删除最后一个节点时存在的段错误
所以只剩下一个节点的时候我们分开处理
*/
while(list->next !=list && list->data == num)
{
list = list->next;
tail->next = list;
r->next = NULL;
free(r);
r = list;
}
/*如果只剩下最后一个节点而且节点的值也等于你要删除的那个值*/
if(list->data == num)
{
free(list);
list = NULL;
return NULL;
}
if(r != list) //删除的是尾巴和中间
{
pre->next = r->next;
r->next = NULL;
free(r);
r = pre->next;
}
}
else
{
pre = r;
r = r->next;
}
}while(r != list);
}
return list;
}
int main(int argc,char *argv[])
{
Node *list = Create_List();
PrintList(list);
ElementType x;
scanf("%d",&x);
list = delete_all_num(list,x);
PrintList(list);
return 0;
}
判断是否为循环链表
#include<stdio.h>
#include<stdlib.h>
struct stu
{
int data;
struct stu *next;
};
typedef struct stu node;
node *plmmnb()
{
node *head,*tail,*p;
head=tail=p=NULL;
int x;
while(1)
{
scanf("%d",&x);
if(x==0)
break;
p=(node *)malloc(sizeof(node));
p->data=x;
p->next=NULL;
if(head==NULL)
{
head=tail=p;
}
else
{
tail->next=p;
tail=p;
}
}
if(head)
tail->next=head;/*如果什么都不输入,那么head等于NULL,不会连接成循环链表,否则输入东西,会成循环列表*/
return head;
}
void panduan(node *B)
{
node *p,*q;
p=q=B;
while(q)
{
p=p->next;
q=q->next;
q=q->next;
if(p==q)//循环链表p会追上q的
break;
}
if(q==NULL)//不是循环链表,跑的快的q会先等于NULL;
{
printf("no\n");
}
else
{
printf("yes\n");
}
}
int main (void)
{
node *B=plmmnb();
panduan(B);
return 0;
}
带头结点的循环链表(报数,1,2,3,逢3退出队伍,下一个重新报数,重新从1开始)
#include<stdio.h>
#include<stdlib.h>
struct stu
{
int data;
struct stu *next;
};
typedef struct stu Node;
struct list
{
Node *first;
Node *last;
int count;
};
typedef struct list List;
List * CreateQueue(void)
{
List *l = (List*)malloc(sizeof(List));
l->first = l->last = NULL;
l->count = 0;
return l;
}
List *EnQueue(List *l,int ch)
{
if(l == NULL)
return ;
//l->count=1;
Node *p;
p = (Node *)malloc(sizeof(Node));
p->data = ch;
p->next = NULL;
if(l->first == NULL)
{
l->first = l->last = p;
}
else
{
l->last->next = p;
l->last = p;
//l->count++;
}
l->count++;
l->last->next=l->first;
return l;
}
void chulai(List *l)
{
int i=1;
Node *p = l->first;
Node *pre=NULL;
while(l)
{
if(i==3)
{
pre->next=p->next;
p->next=NULL;
free(p);
p=NULL;
p=pre->next;
i=1;
l->count--;
}
else
{
pre=p;
p=p->next;
i++;
}
if(l->count==1)
{
printf("剩下%d\n",p->data);
break;
}
}
}
int main (void)
{
List *l = CreateQueue();
while(1)
{
int x;
scanf("%d",&x);
if(x==0)
break;
EnQueue(l,x);
}
chulai(l);
return 0;
}