C语言 双向循环链表的相关操作
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef struct LinkListNode
{
int data;
struct LinkListNode* prior;
struct LinkListNode* next;
}node,*LinkList; //结构体变量类型
void GreatLinklistTail(LinkList* head); // 建立链表
void LinkListInsert(LinkList* head); //插入节点
void LinkListFind(LinkList* head); //查找数据
void LinkListnode_Delete(LinkList* head); //删除节点
void LinkListDatePrint(LinkList* head); //链表的输出
void LinkListClean(LinkList* head); //链表的整表删除
/**
*为了建立、使用、维护链表,对链表的操作如下:
*建立链表
*遍历链表
*尾部追加
*删除结点
*查找结点
*/
/******************************************************************************/
int main(void)
{
LinkList head;
int i;
printf("*************************双向循环链表操作***************************\n\n");
printf("1.初始化双向循环链表\n\n2.插入节点 \n\n3.删除节点 \n\n4,查找节点\n\n0.释放内存操作完成\n\n");
while(1)
{
scanf("%d", &i);
switch(i)
{
case 1:
{
printf("下面进行建立双向循环链表操作!\n");
GreatLinklistTail(&head);
LinkListDatePrint(&head);
}
break;
case 2:
{
printf("下面进行插入节点操作!\n");
LinkListInsert(&head);
LinkListDatePrint(&head);
}
break;
case 3:
{
printf("下面进行建立删除节点操作!\n");
LinkListnode_Delete(&head);
LinkListDatePrint(&head);
}
break;
case 4:
{
printf("下面进行查找数据操作!\n");
LinkListFind(&head);
}
break;
}
if(i == 0)
{
break;
}
}
printf("双向链表操作结束!\n");
LinkListClean(&head);
system("pause");
return 0;
}
/**********************************************************************************/
//双向循环链表初始化操作
void GreatLinklistTail(LinkList* head)
{
node *p, *q = NULL; //声明节点p 和q
int i, j;
*head = (LinkList)malloc(sizeof(LinkList)); //为第一个节点开辟内存
(*head)->next = *head; //将第一个结构体指针的的next 指向第一个节点
(*head)->prior = *head; // 将第一个结构体指针的的prior指向第一个节点
p = *head;
printf("请输入所要开辟节点的个数,输入0退出: \n");
scanf_s("%d", &i);
fflush(stdin);
if(i == 0)
{
return ; //如果输入 0直接退出程序
}
else
{
p = *head; //令p指向第一个节点 便于操作
for (j = 1; j <= i; j++)
{
if(j == 1) //开辟第一个节点时
{
printf("请输入第%d个节点所要存储的数据:", j);
scanf_s("%d", &p->data);
fflush(stdin);
p->next = NULL;
p->prior = NULL;
}
else
{
q = (node*)malloc(sizeof(node)); //为q 开辟内存
if (!q)
{
return; //分配内存失败退出
}
printf("请输入第%d个节点所要存储的数据:", j);
scanf_s("%d", &q->data);
q->prior = p; //q的前驱指针指向 p节点
q->next = p->next; //将尾节点的next指向 空
p->next = q; // p的next指向 q
p = q; //通过循环建立双向链表 //同于建立双向链表
}
}
p->next = *head; //此时p的位置在尾节点处
(*head)->next->prior = p; //头尾互指
}
printf("单链表建立完毕!!!\n\n");
}
//打印数据函数
//链表数据的输出
void LinkListDatePrint(LinkList *head)
{
node *p;
int j = 1;
printf("********************链表中的数据********************\n");
p = *head;
do
{
printf("第%d个节点存储的数为:%d;\n", j, p->data);
j++;
p = p->next; //循环遍历链表算法
}while(p!= *head); //通过循环遍历 到next指向头结点的指针
printf("链表数据打印完毕!!!\n\n");
}
//链表的整表删除
/*思路:
1,声明节点p,q
2,将第一个节点赋给p,下一个赋给 q
3,循环执行释放p和将q赋给p操作
*/
void LinkListClean(LinkList* head)
{
node* p, * q;
p = *head;
while (p->next != *head) //循环释放法则
{
q = p->next;
free(p);
p = q;
}
printf("单链表内存释放成功!!!\n");
}
//链表的数据插入操作
void LinkListInsert(LinkList* head) //插入节点
{
node *p, *s; //声明循环遍历结构体指针p 和 插入节点 s
int i, j = 1;
s = (node*)malloc(sizeof(node)); //为要插入的节点开辟内存
s->next = NULL; //防止成为野指针
s->prior = NULL;
printf("请输入要插入的节点的位置:");
scanf_s("%d", &i);
fflush(stdin);
if(i == 1)
{
printf("请输入插入节点存储的值:");
scanf("%d", &s->data);
fflush(stdin);
for(p = *head; p->next != *head; p= p->next)
; //寻找最后一个节点
s->next = *head;
s->prior = (*head)->prior;
(*head)->prior = s;
p->next = s;
*head = s; //将s作为第一个节点
}
else
{
printf("请输入插入节点存储的值:");
scanf("%d", &s->data);
fflush(stdin);
for(p = *head, j = 1; j < i; j++)
{
p = p->next;
}
s->next = p; //插入关键算法,画图即知
s->prior = p->prior;
p->prior->next = s;
p->prior = s;
}
printf("节点插入成功!!!\n\n");
}
//节点的查找并返回节点的位置
void LinkListFind(LinkList* head) //查找第i个元素
{
node *target;
int i, j = 1;
printf("请输入查找的数据:");
scanf_s("%d", &i);
fflush(stdin);
for (target = *head; target->data != i && target->next != *head; target = target->next)
j++; //循环遍历寻找最后一个节点
printf("该节点的位置是: %d\n\n", j);
}
//单链表节点删除操作
void LinkListnode_Delete(LinkList* head)
{
node *p, *target; //声明节点p指向链表的第一个节点
int i; //要删除的节点
int j = 1; //声明一个计数器
p = *head; //p节点指向第一个节点
printf("请输入要删除的节点标号:");
scanf_s("%d", &i);
fflush(stdin);
if (i == 1)
{
for (target = *head; target->next != (*head); target = target->next)
; //循环遍历寻找最后一个节点
target->next = p->next;
p->next->prior = target;
*head = p->next; //把第二个节点再当成第一个节点
free(p);
}
else
{
for(j = 1; j < i; j++)
{
p = p->next; //找到第i个节点
}
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
printf("节点删除成功!!!!\n\n");
}
}