- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试按字母顺序创建名称链接列表,我注意到这是一个半常见的问题,但我在实现时遇到了一些困难。
所以,我的看法是,该项目可以添加到链表的开头、中间或末尾,我想我很难将其添加到末尾。
这是我对 bool 值的实现:
typedef int bool;
#define TRUE 1
#define FALSE 0
这是我的节点/项目/结构:
typedef struct student_s Student;
struct student_s {
char name[MAX_NAME_SIZE];
int age;
Student* next; // Pointer to next student in a list
};
我的比较函数:
// Compares two student structs based on their name and age, and returns true
// if student1 should come before student2 in alphabetical order
bool comesBefore(const Student* student1, const Student* student2) {
int name_compare = strcmp(student1->name, student2->name);
if (name_compare < 0) {
return TRUE;
}
else if (name_compare == 0) {
int age1 = student1->age;
int age2 = student2->age;
if (age1 < age2) {
return TRUE;
}
}
return FALSE;
}
我的插入函数:
Student* insert(Student* student, Student* list) {
Student* curr = NULL;
Student* prev = NULL;
if (list == NULL) {
printf("list == null\n");
return student;
}
if (comesBefore(student, list)) {
printf("Student comes before list\n");
printf("Student age = %d\n", student->age);
printf("List age = %d\n", list->age);
student->next = list;
return student;
}
for (curr = list, prev = NULL; curr != NULL && comesBefore(student,
curr) != TRUE; prev = curr, curr = curr->next) {
printf("Stage 1\n\n");
printf("curr age = %d\n", curr->age);
printf("student age = %d\n", student->age);
if (comesBefore(student, curr)) {
printf("Stage 2\n");
if (prev != NULL) {
prev->next = student;
}
student->next = curr;
break;
}
if ((curr->next) == NULL) {
printf("Appended at the end of the list\n");
curr->next = student;
break;
}
}
return list;
}
我的主要功能是所有测试:
int main(void)
{
Student* student1 = malloc(sizeof(Student));
Student* student2 = malloc(sizeof(Student));
Student* student3 = malloc(sizeof(Student));
strncpy(student1->name, "AAAAA", MAX_NAME_SIZE);
student1->age = 10;
student1->next = NULL;
student2->next = NULL;
student3->next = NULL;
strncpy((*student2).name, "BBBBB", MAX_NAME_SIZE);
(*student2).age = 100;
strncpy((*student3).name, "CCCC", MAX_NAME_SIZE);
(*student3).age = 1000;
Student* list1 = insert(student1, NULL);
Student* list2 = insert(student3, list1);
Student* list3 = insert(student2, list2);
printf("head %d\n", list3->age);
printf("second element %d\n", (list3->next)->age);
printf("third element %d\n", ((list3->next)->next)->age);
}
问题是我一直遇到段错误。我认为是当 next 设置为 NULL 时我尝试访问列表中的下一个节点 (curr->next),但无论出于何种原因我的 if 语句
if ((curr->next) == NULL) {
printf("Appended at the end of the list\n");
curr->next = student;
break;
}
永远不会被触发。为什么?还是我完全错了?
最佳答案
问题是您的插入函数在一般情况下并没有真正插入。查看循环体:
for (curr = list, prev = NULL; curr != NULL && comesBefore(student,
curr) != TRUE; prev = curr, curr = curr->next) {
printf("Stage 1\n\n");
printf("curr age = %d\n", curr->age);
printf("student age = %d\n", student->age);
if (comesBefore(student, curr)) {
printf("Stage 2\n");
if (prev != NULL) {
prev->next = student;
}
student->next = curr;
break;
}
if ((curr->next) == NULL) {
printf("Appended at the end of the list\n");
curr->next = student;
break;
}
}
只有在curr != NULL && comesBefore(student, curr) != TRUE
时才进入循环体, 所以 if (comesBefore(student, curr))
在循环内永远不会为真。
相反,您希望在循环终止后插入,即在循环之后。你也不需要 if ((curr->next) == NULL)
在循环内;如果是,则循环将再迭代一次,curr
将是 NULL
和 prev
将是您感兴趣的指针。循环条件写得很好,您只是在错误的地方做事。
这会起作用:
for (curr = list, prev = NULL;
curr != NULL && comesBefore(student, curr) != TRUE;
prev = curr, curr = curr->next) {
printf("Stage 1\n\n");
printf("curr age = %d\n", curr->age);
printf("student age = %d\n", student->age);
}
student->next = curr;
prev->next = student;
return list;
这是此修复后的整个函数:
Student* insert(Student* student, Student* list) {
Student* curr = NULL;
Student* prev = NULL;
if (list == NULL) {
printf("list == null\n");
return student;
}
if (comesBefore(student, list)) {
printf("Student comes before list\n");
printf("Student age = %d\n", student->age);
printf("List age = %d\n", list->age);
student->next = list;
return student;
}
for (curr = list, prev = NULL;
curr != NULL && comesBefore(student, curr) != TRUE;
prev = curr, curr = curr->next) {
printf("Stage 1\n\n");
printf("curr age = %d\n", curr->age);
printf("student age = %d\n", student->age);
}
student->next = curr;
prev->next = student;
return list;
}
当你完成调试后,循环体将是空的;您可能想添加一条评论说这是有意的(我通常喜欢这样做,以便其他阅读代码的人知道这不是错误)。像这样的东西:
Student* insert(Student* student, Student* list) {
Student* curr = NULL;
Student* prev = NULL;
if (list == NULL)
return student;
if (comesBefore(student, list)) {
student->next = list;
return student;
}
for (curr = list, prev = NULL;
curr != NULL && comesBefore(student, curr) != TRUE;
prev = curr, curr = curr->next)
; /* Intentionally left blank */
student->next = curr;
prev->next = student;
return list;
}
此外,您不需要测试 prev != NULL
,因为如果到达循环,那么我们就知道 comesBefore(student, list)
为 false(因为我们在代码的前面测试过),所以循环将始终至少执行一次。对于 self 文档(并确保 future 的代码更改不违反此变体),您可能需要添加 assert(3)
循环之后,像这样:
Student* insert(Student* student, Student* list) {
Student* curr = NULL;
Student* prev = NULL;
if (list == NULL)
return student;
if (comesBefore(student, list)) {
student->next = list;
return student;
}
for (curr = list, prev = NULL;
curr != NULL && comesBefore(student, curr) != TRUE;
prev = curr, curr = curr->next)
; /* Intentionally left blank */
assert(prev != NULL);
student->next = curr;
prev->next = student;
return list;
}
您需要 #include <assert.h>
使用 assert(3)
.
关于c - 使用尾随指针将节点插入链表 C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32225821/
考虑 this link来自 Bit Twiddling Hacks 网站。为了计算尾随位,使用了以下算法: unsigned int v; // 32-bit word input to
我正在开发一个在输出目录中创建多个文件的 makefile。为了创建这些文件,输出目录需要已经存在,否则文件创建失败。 这是一个演示我遇到的问题的最小示例: .PHONY: default defau
我试图让 TextField 的值以尾随对齐方式显示。 如您所见,值 34.3 以前导对齐方式显示。 我确信我遗漏了一些明显的东西,但我不知道是什么。有什么想法吗? @State private va
我想让我的 StackView 在屏幕上居中,并在每边(左和右)添加一个 20 的填充以获得屏幕边距: 但不考虑左边距: 结果如下: 如何处理右边距?对于其他类型的对象(不是 StackView),我
我们在我们的网站上使用漂亮的网址。几年前我有一个外部技术人员添加反向链接。他做得很好,但在一个案例中,他总是添加一个尾随空格字符的链接。 https://www.example.com/item/it
我正在设计一个带前缀的可变长度整数。 Rust 具有计算前导和尾随 1 和 0 的方法:https://doc.rust-lang.org/std/primitive.u64.html#method.
Passing a lambda to the last parameter In Kotlin, there is a convention that if the last parameter o
我需要正则表达式的帮助来从字符串中去除不需要的字符(在 Java 中)。我用 4 个正则表达式解决了这个问题。替换将被多次调用 [peeks: 50+ times/sec] 它并降低性能。但我认为它肯
如果我用 base64 编码一个由七个字符组成的字符串,例如abcdefg 与网站 https://www.base64encode.org/结果是 YWJjZGVmZw==。尾部的“==”字符被填充
尝试在客户端上使用 sprintf 打印出包含缓冲区的 char[]。最后一个字符是“\0”。这是我的服务器代码: char buffer[MAXDATASIZE]; char res[MAXDATA
我在 angular2 项目中遇到问题,我正在生成一个要通过电子邮件发送给用户的 URL。电子邮件中的 URL 需要包含一个特殊 ID,该 ID 在路由器中传递为: { 路径:somepath/:id
我正在尝试删除所有前导和尾随 在使用 PHP 的字符串中。 举个例子 Hello World This is a message... 我想回去 Hello World This is a mes
我有一个 JSON 输出,我想稍微修改一下: JSON={"type":"global", "elements":[ {"type":"car","model":"bmw", "element
继续阅读 ranges-v3 库,我意识到所有关于模板类型有效表达式的检查都有一个尾部 ", 42"表达式,我想知道这样做的目的是什么。例如: namespace concepts { con
我使用的是最新版本的 Xcode (11 Beta 16) 和 macOS (10.15 Beta 6) 我正在尝试创建两个 View 。从第一个 View ,您应该能够通过尾随导航栏项目导航到第二个
我在使用 SwiftUI 时遇到性能问题 List有大量数据。我创建了一个演示应用程序只是为了展示 500_000 String 的问题s 并显示其中一个的尾随 Action ,CPU 将在几秒钟内达
我正在使用 Blue River 的最新 docker 镜像,运行 docker-compose 启动它并在 Mura CMS 中部署一个站点包。 问题是,当我访问 URL 后面没有正斜杠的页面时,我
我是一名优秀的程序员,十分优秀!