单向循环链表的增、删和打印
#include <stdio.h>
#include<stdlib.h>
typedef struct Node{
int data;
struct Node* next;
}Node,*LinkList;
struct Node* InitLinkList(LinkList L)
{
L = (Node *)malloc(sizeof(Node));
L->data = 0;
L->next = L;
return L;
}
void CreateLinkList(LinkList L,int x) // 头插法
{
struct Node *s;
s = (Node *)malloc(sizeof(Node));
s->data = x;
s->next = L->next;
L->next = s;
}
int Print(LinkList L)
{
if(L->next == L) return 0;
struct Node* rear = L->next;
while(rear != L){
printf(" 输出的值为:");
printf("%d\n",rear->data);
rear = rear->next;
}
return 0;
}
void del(LinkList L,int x)
{
struct Node* del = L->next; // 跳过头结点,头结点是空的
struct Node* fr;
while(del != L){ // 循环终止的条件是当del重新指向L的时候
if(del->next->data == x){ // 如果下一个结点的值是要删除的值,那么就跳过他
fr = del->next;
del->next = del->next->next;
free(fr);
}
del = del->next;
}
if(del->next->data == x){ // 由于直接判断了下一个条件,所以要在后面加一个对头结点后的第一个值的判断
L->next = L->next->next;
fr = L->next;
free(fr);
}
}
int main()
{
struct Node* L;
int x;
L = InitLinkList(L);
for(int i = 1;i < 6;i++){
CreateLinkList(L, i);
}
Print(L);
printf("请输入要删除的值:");
scanf("%d",&x);
del(L,x);
Print(L);
return 0;
}
(1)对于链表的初始化,要注意函数形式参数的传值。
int i = 5;
Node* L 或者 LinkList L 类似于i(i的值5), 对于这种情况在函数调用的时候要用i,不可以正常使用,要有返回值(原因是他改变了L的地址,为L创建了新的结点空间).
Node** L 或者 LinkList L 类似于i(i的地址),对于这种情况在函数调用的时候要用&i,这种方法可以正常使用,因为操作时都是对相应的地址进行操作
(2)采用头插法创造结点,在初始化的过程中,要把头结点的next指向自己(单循环链表)
(3)输出的时候与输入的顺序刚好相反,要在输出之前先判定输出的链表是不是空的,结束的判定条件是rear != L
(4)在创造结点的时候没有对L的地址进行更改,只是指针不一样了,但是L本身的地址没有改变,所以不需要返回值或者传地址