数据结构:线性表(循环单链表)C语言简单实现
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define _CRT_SECURE_NO_WARNINGS
#define ok 1
#define error -1
typedef int Elemtype;
typedef int Status;
//带头结点的
typedef struct LNode
{
Elemtype data;
struct LNode *next;
} LNode, *LinkList; //*LinkList为LNode类型的指针
//头插法建立单链表(插入顺序和打印顺序相反)
LinkList HeadInsert(LinkList L, int n)
{
LNode *s;
int i;
L = (LinkList)malloc(sizeof(LNode)); // 创建头结点的空间
L->data = NULL;
L->next = NULL; // 空链表
for (i = 0; i < n; i++)
{
if(L->next == NULL) // 插入第一个结点
{
s = (LNode *)malloc(sizeof(LNode));
scanf("%d", &s->data);
s->next = L; //头插法最后一个元素指向头结点
L->next = s;
}else{
s = (LNode *)malloc(sizeof(LNode));
scanf("%d", &s->data);
s->next = L->next;
L->next = s;
}
}
printf("头插法建立单链表成功\n");
return L;
}
//尾插法建立单链表(一样的顺序)
LinkList TailInsert(LinkList L, int n)
{
int i;
L = (LinkList)malloc(sizeof(LNode)); // 创建头结点的空间
L->data = NULL; // 头结点的data置为NULL
LNode *s, *r = L; // r为尾指针
for (i = 0; i < n; i++)
{
s = (LNode *)malloc(sizeof(LNode));
scanf("%d", &s->data);
r->next = s;
r = s; // r 指向新的表尾结点
}
r->next = L; // 尾结点指针指向头结点(和单链表的不同)
printf("尾插法建立单链表成功\n");
return L;
}
//打印链表
Status print(LinkList L)
{
int n;
LNode *s = L->next; //从第一个结点开始
while (s->data != NULL) //结束条件就是循环到头结点(头结点的data为NULL)
//与单链表不一样的地方
{
printf("%d ", s->data);
s = s->next;
}
printf("\n");
return ok;
}
//求表长
Status Length(LinkList L)
{
LNode *s;
s = L->next;
int i = 0;
if (s == NULL)
{
printf("空表\n");
return error;
}
else
{
while (s->data != NULL) //与单链表不一样的地方
{
i++;
s = s->next;
}
return i;
}
return error;
}
//按序号查找表结点
LNode *GetElem(LinkList L, int pos)
{
int j = 1; // 用于计数
LNode *s = L->next; // 从第一个结点开始
if (pos == 0)
//返回值也为空
return L;
if (pos < 1)
return NULL;
while ((s->data != NULL) && j < pos)
{ //从第一个结点开始,直到第pos个结点为止
s = s->next;
j++;
}
//找到了或者没找到为空
return s;
}
//删除表尾结点
Status Delete(LinkList L, int pos)
{
LNode *p, *q;
if (pos < 0 || pos >= Length(L) + 1)
return error;
p = GetElem(L, pos - 1); // p 指向删除结点的前驱结点
q = p->next; // q指向要删除的结点
p->next = q->next; // 表尾结点的next指针就指向了头结点
free(q);
print(L);
return ok;
}
//插入结点(i-1的位置后插法)
Status Insert(LinkList L, int pos)
{
if (pos < 0 || pos > Length(L) + 1)
return error;
LNode *s, *p;
s = (LNode *)malloc(sizeof(LNode));
printf("请输入要插入结点的值为:");
scanf("%d", &s->data);
p = GetElem(L, pos - 1); // 插入位置的前驱结点
s->next = p->next; // 表尾结点又指向了头结点
p->next = s;
print(L);
return ok;
}
int main()
{
//循环单链表和单链表在插入、删除操作上一样,就不写了
//不同的就是表尾插入,删除时要保持循环的结构
int i;
LinkList L;
//头插法
//L = HeadInsert(L,5);
//尾插法
L = TailInsert(L,5);
i = Length(L);
printf("表长为:%d\n",i);
print(L);
printf("删除表尾结点后链表:");
//删除表尾结点
Delete(L,5);
printf("\n");
printf("表尾插入结点后链表:\n");
Insert(L,5);
}
效果如下: