带头节点的单向循环链表
头指针指向第一个结点的地址,当头指针为空时,链表为空。
建立
typedef struct
{
char name[20];
float score;
} STD;
typedef STD ElemType;
typedef struct Londe
{
ElemType data; //data是一个STD类型的变量
struct Lnode *next;
}LNode,*LinkList; //LNode是结点数据类型,LinkList为指向节点的指针类型
初始化
带头结点的链表更加常用
int initList(LinkList *L)
{
*L = (LinkList)malloc(sizeof(Lnode)); //L是指向头指针的指针变量,(*L)是头指针,头指针指向头结点位置
if(*L == NULL)
return 0;
(*L)->next = NULL; //头结点为空
return 1;
}
调用:
int main()
{
LinkList L;
if(LinkList(&L))
printf("初始化成功!\n");
else
printf("初始化失败!\n");
}
插入
主要变化就是原本的判断是否为空变成了判断是否为头结点
- 任意位置插入
int insertList(LinkList L, int i, ElemType e)
{
LinkList p = L, s; //p指向头结点
int pos = 0; //记住p
while (p->next != L && pos < i - 1)
{
p = p->next;
pos++;
}
if (p->next == L && pos<i-1|| pos > i - 1)
return 0;
s = (LinkList)malloc(sizeof(Lnode));
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
调用:
ElemType e;
printf("请输入需要插入的数据\n:");
scanf("%s%f", &e.name, &e.score);
int pos;
printf("请输入需要插入的位置:\n");
scanf("%d", &pos);
if (insertList(&L, pos, e) != 0)
printf("插入成功!\n");
else
printf("插入位置不合理,失败!\n");
- 头插
头指针指向新节点,新节点下一个为原来的头结点,没有遍历
int frontinsertList(LinkList L,ElemType e)
{
LinkList p;
p = (LinkList)malloc(sizeof(Lnode));
p->data = e;
p->next = L->next;
L->next = p;
return 1;
}
- 尾插
int rearinsertList(LinkList L, ElemType e)
{
LinkList p,q = L;
p = (LinkList)malloc(sizeof(Lnode));
p->data = e;
while (q->next != L)
q = q->next;
q->next = p;
p->next = L;
return 1;
}
删除
删除指定位置:
int deleteList(LinkList L, int i)
{
LinkList q,p = L;
int pos = 0;
if (p->next == L)
return 0;
while (p->next != L && pos<i-1)
{
p = p->next;
pos++;
}
q = p->next;
p->next = q->next;
free(q);
return 1;
}
调用:
ElemType e;
int pos;
printf("请输入需要删除的数据的位置:\n");
scanf("%d", &pos);
if (deleteList(L, pos))
printf("删除成功!\n");
else
printf("删除失败!\n");
printf("最新的数据表为:\n");
修改
int reviseList(LinkList L, int i, ElemType e)
{
LinkList p = L->next;
int n = 1;
while (p != L && n < i)
{
p = p->next;
n++;
}
if (p == L || n > i)
return 0;
p->data = e;
return i;
}
调用:
ElemType e;
printf("请输入需要修改的数据的位置:");
int pos;
scanf("%d", &pos);
printf("请输入需要修改的数据:");
scanf("%s%d", & e.name, &e.time);
if (reviseList(L, pos, e))
printf("修改成功!");
else
printf("修改失败!");
遍历(打印)
int printList(LinkList L)
{
LinkList p = L->next;
if (p == L)
return 0;
while (p!=L)
{
printf("%s%d\n", p->data.name, p->data.time);
p = p->next;
}
return 1;
}
调用:
printList(L);
其余操作也同理,只是把判断条件换成了p != L
实例
采用循环单单链表保存图书信息(书名,书号),完成以下功能:1)初始化创建包含3个数据元素的表(按书号升序排列);2)按书号有序插入数据元素;3)按书号删除数据元素;4)输出。
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
char name[20];
int no;
} BOOK;
typedef BOOK ElemType;
typedef struct Lnode
{
ElemType data;
struct Lnode* next;
}Lnode, * LinkList;
int initList(LinkList* L)
{
*L = (LinkList)malloc(sizeof(Lnode)); //L是指向头指针的指针变量,(*L)是头指针,头指针指向头结点位置
if (*L == NULL)
return 0;
(*L)->next = *L; //头结点是头指针
return 1;
}
int ListLength(LinkList L)
{
LinkList p = L->next;
int n = 0;
if (p == L)
return 0;
while (p != L)
{
p = p->next;
n++;
}
return n;
}
int sortinsertList(LinkList *L, ElemType e)
{
LinkList p = *L, s; //p指向头结点
int pos = 0; //记住p
while (p->next != *L && pos < ListLength(*L) - 1 && e.no > p->next->data.no)
{
p = p->next;
pos++;
}
if (p->next == *L || pos > ListLength(*L) - 1)
return 0;
s = (LinkList)malloc(sizeof(Lnode));
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
int deleteList(LinkList L, int i)
{
LinkList q,p = L;
int pos = 0;
if (p->next == L)
return 0;
while (p->next != L && pos<i-1)
{
p = p->next;
pos++;
}
q = p->next;
p->next = q->next;
free(q);
return 1;
}
int creatList(LinkList *L)
{
initList(L);
LinkList p,q = *L;
ElemType e[3];
e[0] = { "第一本书",3 };
e[1] = { "第二本书",6 };
e[2] = { "第三本书",9 };
int n = 0;
do
{
p = (LinkList)malloc(sizeof(Lnode));
p->data = e[n];
p->next = (*L);
q->next = p;
q = p;
n++;
} while (n < 3);
return 1;
}
int printList(LinkList L)
{
LinkList p = L->next;
if (p == L)
return 0;
while (p!= L)
{
printf("%s的编号为:%d\n", p->data.name, p->data.no);
p = p->next;
}
return 1;
}
int main()
{
LinkList L;
creatList(&L);
printf("创建成功!\n最新的数据表为:\n");
printList( L);
printf("\n请选择你要执行的操作\n");
printf("1 : 插入新数据\n");
printf("2 : 删除数据\n");
printf("3 : 根据事件修改\n");
printf("4 : 根据事件查询\n");
int op;
while (scanf("%d", &op) && op) {
if (op == 1) {
ElemType e;
printf("请输入需要插入的数据:\n");
scanf("%s%d", &e.name, &e.no);
if (sortinsertList(&L, e) != 0)
printf("插入成功!\n");
else
printf("插入位置不合理,失败!\n");
printf("最新的数据表为:\n");
printList( L);
}
else if (op == 2) {
ElemType e;
int pos;
printf("请输入需要删除的数据的位置:\n");
scanf("%d", &pos);
if (deleteList(L, pos))
printf("删除成功!\n");
else
printf("删除失败!\n");
printf("最新的数据表为:\n");
printList(L);
}
}
}