明天我参加考试,我试图理解教师在课堂网站上放置的这个双重链接列表示例,但我很难理解它...
以下是代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct dl {
int key;
float value;
struct dl *next;
struct dl *prev;
} DL;
DL *insert(int c, float f, DL *l) {
DL *new = (DL*) malloc(sizeof(DL));
if (new == NULL) exit(-1);
new->key=c; new->value=f;
if (l==NULL) {
new->next=NULL; new->prev=NULL;
}
else if (l->key < c) {
while((l->next != NULL) && (l->next->key < c)) { l=l->next; }
new->next=l->next; l->next=new; new->prev=l;
if (new->next != NULL) {
new->next->prev=new;
}
}
else {
while((l->prev != NULL) && (l->prev->key > c)) { l=l->prev; }
new->prev=l->prev; l->prev=new; new->next=l;
if(new->prev != NULL) {
new->prev->next=new;
}
}
return new;
}
int search(int c, float *f, DL **lptr) {
if (*lptr == NULL) return 0;
if (c < (*lptr)->key) {
while(((*lptr)->prev!=NULL)&&((*lptr)->prev->key >= c)) {
(*lptr)=(*lptr)->prev;
}
}
else if (c > (*lptr)->key) {
while(((*lptr)->next!=NULL)&&((*lptr)->next->key <= c)) {
(*lptr)=(*lptr)->next;
}
}
if ((*lptr)->key == c) {
*f = (*lptr)->value;
return 1;
}
return 0;
}
void printList(DL *l) {
if (l == NULL) return;
while (l->prev != NULL) { l=l->prev; };
while(l != NULL) {
printf("%d,%f\n",l->key,l->value);
l=l->next;
}
}
int main(void) {
DL *list=NULL;
float f;
list=insert(3,5.6,list); list=insert(4,5.3,list);
list=insert(7,3.6,list); list=insert(1,7.7,list);
list=insert(9,2.3,list); list=insert(0,9.0,list);
printList(list);
if (search(3,&f,&list)) {
printf("Found %f.\n",f);
}
else {
printf("Not found.\n");
}
printList(list);
return 0;
}
这是输出:
0,9.000000
1,7.700000
3,5.600000
4,5.300000
7,3.600000
9,2.300000
Found 5.600000.
0,9.000000
1,7.700000
3,5.600000
4,5.300000
7,3.600000
9,2.300000
我没有得到的是“搜索”功能。传递的列表是指向DL的指针,对吧?我们正在寻找一个数字,因为我们继续做(* lptr)=(* lptr) - &gt; next (或prev)来遍历整个列表。我没有得到的是为什么第二次调用printList()打印整个列表...在调用search()之后,“list”不应该只有我们查找的元素之后的元素吗?指针被更改了,当我们从search()返回时,指针是否恢复到第一个元素并打印整个列表?
如果我更改search()函数并在第一行添加(* lptr)= NULL ,则第二行调用printList()将无法打印什么,导致指针被更改,现在是NULL,没有什么可以打印。为什么(* lptr)=(* lptr) - &gt; next 有类似的效果?指针也被改为下一个,不应该第二个printList()调用只打印列表中的其余元素吗?
修改
每个答案似乎都是正确的,我会按“最老的”排序并接受“最快的”,不要生气,我需要有一些标准。我可以继续看看哪个回答提供了更好的洞察力,但这是无关紧要的,因为我已经知道所说的一切。我只是愚蠢到甚至没有查看printList()函数并假设它没问题,我还假设错误是在search()函数的某个地方。但我知道我是对的,我知道指针正在改变而且列表无法打印所有内容,但我明白为什么现在......
答案 0 :(得分:5)
printList
在打印之前将列表重新排列。
while (l->prev != NULL) { l=l->prev; };
如果它没有上面的那一行,它只会在找到的元素之后打印出来。
答案 1 :(得分:4)
此行返回指针:
while (l->prev != NULL) { l=l->prev; };
那些人进行印刷:
while(l != NULL) {
printf("%d,%f\n",l->key,l->value);
l=l->next;
}
这样做有更好的方法,只需添加额外的字段,或者甚至两个字段,它们总是指向列表的开头和结尾。
答案 2 :(得分:2)
据我所知(和rmeador评论,这是非常糟糕的代码),search
调用会修改list
指针以指向找到的元素。
技巧是printList函数。 它做的第一件事(除了检查NULL)是这样的:
while (l->prev != NULL) { l=l->prev; };
因此它基本上跟随prev
指针返回到列表的开头,因此实际打印从列表的开头开始,即使它被传递到指针的中间或末尾。
答案 3 :(得分:1)
在printList()函数中,您将使用l = l->prev
从找到的元素返回。然后你打印所有的内容。
答案 4 :(得分:1)
我没有得到的是为什么第二个 调用printList()打印整个 list ...在search()调用之后 已经制作,不应该只是“列表” 拥有我们之后的元素 找了?指针被改变了, 我们从搜索返回时怎么样() 指针恢复到第一个 元素和整个列表打印?
你所拥有的并不是指向列表的指针,而是指向列表中元素的指针。 printList函数首先通过prev引用循环回来查找列表的第一个元素。
答案 5 :(得分:1)
他回溯了打印内的指针:
while (l->prev != NULL) { l=l->prev; };
请记住,列表是双重链接的。搜索不会更改列表,只是“list”的哪一部分目前指向。