双向循环链表的增删查改
#include <stdio.h>
#include <stdlib.h>
// 双向循环链表的节点设计
typedef struct node{
int data; // 数据域
// 指针域
struct node *prev; // 指向其逻辑上的前一个节点
struct node *next; // 指向其逻辑上的后一个节点
}node;
// 遍历(后序遍历)
void link_list_show(node *head);
// 遍历(前序遍历)
void link_list_show_prev(node *head);
// 头插
void link_list_add(int new_data, node *head);
// 尾插
void link_list_add_tail(int new_data, node *head);
// 删除节点
void link_list_del(int del_data, node *head);
// 给节点分配堆空间
node *link_list_init(void);
int main(int argc, char const *argv[])
{
// 1.初始化一条空链表
node *head = link_list_init();
// 2.数据操作
int cmd;
while(1)
{
printf("pls input cmd!\n");
scanf("%d", &cmd);while(getchar()!='\n');
if(cmd > 0)
// link_list_add(cmd, head); // 头插
link_list_add_tail(cmd, head); // 尾插
else if(cmd < 0)
link_list_del(-cmd, head);
//输入0退出
else
break;
printf("前序:");
link_list_show_prev(head); // 前序遍历
printf("后序:");
link_list_show(head); // 后序遍历
}
return 0;
}
// 删除节点
void link_list_del(int del_data, node *head)
{
//1.判断链表是否为空
if(head->next == head)
{
printf("list is empty!\n");
return ;
}
//2.定义两个指针,遍历链表找到欲删除节点和其前一个节点
node *pos_prev = head;
node *pos_del;
for(pos_del=head->next; pos_del!=head; pos_del=pos_del->next)
{
if(pos_del->data == del_data) // 找到了
break;
//如果当前节点不是欲删除节点,往后走
pos_prev = pos_del; // pos_prev=pos_prev->next;
}
//2.1如果循环正常结束,则未找到
if(pos_del == head)
{
printf("Not found\n");
return ;
}
//2.2如果找到就修改指针指向
//欲删除节点的前一个节点的指针域,指向欲删除节点的后一个节点
pos_prev->next = pos_del->next;
pos_del->next->prev=pos_prev;
//3.释放欲删除节点的堆空间
free(pos_del);
}
// 尾插
void link_list_add_tail(int new_data, node *head)
{
//法一
/* // 1.给新节点分配堆空间,把数据写入
node *new = link_list_init();
new->data = new_data;
// 2.修改指针的指向
// 2.1修改新节点的指针指向
new->prev = head->prev; // 新节点的前指针指向尾节点
new->next = head; // 新节点的后指针,指向头节点
// 2.2尾节点的指针next指向新节点
head->prev->next = new;
// 2.3头节点的指针prev指向新节点
head->prev = new; */
//法二
// 调用头插实现尾插
link_list_add(new_data, head->prev);
}
// 遍历(后序遍历)
void link_list_show(node *head)
{
node *pos;
for(pos=head->next; pos!=head; pos=pos->next)
{
printf("%d ", pos->data);
}
printf("\n");
}
// 遍历(前序遍历)
void link_list_show_prev(node *head)
{
node *pos;
for(pos=head->prev; pos!=head; pos=pos->prev)
{
printf("%d ", pos->data);
}
printf("\n");
}
// 头插
void link_list_add(int new_data, node *head)
{
// 1.给新节点申请内存空间,并将数据写入
node *new = link_list_init();
new->data = new_data;
// 2.修改指针指向
// 2.1先操作新节点的前后指针,
new->prev = head; // 新节点的前指针prev指向头节点
new->next = head->next; // 后指针指向第一个有效数据节点
// 2.2操作头节点的下一个节点的指针,使其的前指针指向新节点
head->next->prev = new;
// 2.3操作头节点的指针next指向新节点
head->next = new;
}
// 给节点分配堆空间
node *link_list_init(void)
{
// 1.申请堆空间
node *p = malloc(sizeof(node));
if(NULL == p)
{
perror("malloc failed!\n"); // perror可以将错误原因打出来
return NULL;
}
// 2.清空节点
p->data = 0;
p->prev = p; // 指针域指向自己
p->next = p; // 指针域指向自己
// 3.将堆空间的地址返回给head
return p;
}