c - 删除双循环链表中节点的正确方法
问题描述
此代码的目的是管理插入和删除以及可视化。我只想知道我是否正确地做所有事情,让我知道是否有更多可能的方法来做到这一点。这是我的第一次尝试,我没有遵循任何教程。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
int n;
struct Node *next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(Node *pp, int n)
{
Node temp, last;
temp = (Node)malloc(sizeof(struct Node));
temp->n = n;
temp->next = temp;
temp->prev = temp;
if(*pp != NULL)
{
last = (*pp)->prev;
temp->next = (*pp);
temp->prev = last;
last->next = (*pp)->prev = temp;
}
*pp = temp;
}
void ViewList(Node head)
{
if(head == NULL)
{
return;
}
Node node = head->prev;
do
{
printf("Curr: %d\n", node->n);
node = node->prev;
}while(node != head->prev);
}
void ReadData(Node * head, int * n)
{
printf("\nInsert a number:");
scanf("%d", n);
NewNode(head, *n);
}
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
while(head != NULL)
{
if(head->n == d)
{
return head;
}
head = head->next;
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
void Delete(Node * head)
{
Node del = SearchNode(*head);
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del && del->next == *head)
{
*head = NULL;
free(del);
return;
}
if(*head == del)
{
*head = del->next;
del->prev->next = *head;
(*head)->prev = del->prev;
free(del);
return;
}
if((*head)->prev == del)
{
(*head)->prev = del->prev;
del->prev->next = *head;
free(del);
return;
}
del->next->prev = del->prev;
del->prev->next = del->next;
free(del);
}
int Menu()
{
int c;
printf("\n*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c,n;
Node head = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadData(&head, &n); break;
case 2: ViewList(head); break;
case 3: Delete(&head); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
我如何测试这是否是一个真正的循环双向链表而不是一个简单的双向链表?
解决方案
您的程序运行良好,我检测到的唯一真正的错误是SearchNode
:如果列表中不存在该元素,则进入无限循环。您的列表显然是一个循环列表,因此您需要检查您是否回到了函数的开头,这意味着您要搜索的元素不在列表中:
修正版:
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
Node start = head; // remember where we started
while (head != NULL)
{
if (head->n == d)
{
return head;
}
head = head->next;
if (head == start) // if we are back to where we started
break; // the element hasn't been found and we stop the loop
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
还有一些设计缺陷,不会阻止程序正常工作:
其中之一是:该n
变量不在外部使用ReadData
,因此在其中声明它main
并将其指针传递给ReadData
.
修正版:
void ReadData(Node * head)
{
int n; // declare n locally
printf("\nInsert a number:");
scanf("%d", &n);
NewNode(head, n);
}
像这样称呼它:ReadData(&head)
并int n;
从main
.
推荐阅读
- angular - 以角度延迟加载每个组件是个好主意吗?
- c# - DryIoc 与 ASP.NET WebApi 和 HostingEnvironment.QueueBackgroundWorkItem() 的正确用法是什么?
- html - Internet Explorer 11 的 webkit 线夹的替代方案?
- javascript - 调用时暂停执行的函数,直到用户在输入中输入值然后按回车键,然后从函数返回值
- javascript - 在同一窗口(选项卡)中打开链接之前转到页面顶部。如何?
- php - 使用 imagick 创建具有渐变颜色的线条
- python - 为什么选择小部件在散景中不起作用?
- networkx - 没有自环的随机多重图
- azure-service-fabric - Service Fabric 的属性管理 API 和 Traefik 扩展
- git - 上游接受来自本地分支的拉取请求后的 Git 工作流