【发布时间】:2017-10-20 04:24:30
【问题描述】:
我一直在阅读 Donald Knuth 第二版的计算机编程艺术第 3 卷中的排序和搜索算法。我在第 95 页遇到了 Knuth 称之为“列表插入”(传统插入排序的一种修改)的算法。
在该页面上,Knuth 得出结论,“用于直接插入的正确数据结构是单向链接线性列表。”并且“链接分配(第 2.2.3 节)非常适合插入,因为只有一个很少有链接需要更改。”但是,第 97 页的 MIXAL 程序(程序 L)似乎没有利用传统的链表结构(一系列由地址链接的节点)。相反,键和链接似乎一起存储在一个类似结构的结构中,这些结构存储在一个名为INPUT 的数组中。
我决定尝试在 C 中实现这个算法。我提供了 Knuth 对算法的描述,以及他在 MIXAL 汇编语言中的实现作为参考。我决定让键本身成为data 数组中的元素,并将链接放在一个名为links 的类似并行的数组中。我说“类并行数组”是因为links 数组的大小比data 数组的大小大一。我这样做是为了可以通过将data 数组的最小元素存储为links 数组中的第一个元素来轻松确定它的索引。由于links 中的这个额外索引,data 数组的索引 0 - (n - 1) 对应于links 数组的索引 1 - n。 links 数组中的每个元素对应于排序列表中下一个元素在data 数组中的索引。
我的问题是,根据他的描述,这个算法应该是这样实现的,还是我遗漏了什么?
int *listInsertion(int data[], int n) {
if (n > 1) {
int i, j, entry;
int *links = (int *) calloc(n + 1, sizeof *links);
links[n] = -1;
links[n - 1] = n - 1;
for (i = n - 2; i >= 0; i--) {
entry = data[i];
for (j = i + 1; links[j] >= 0 && entry > data[links[j]];
j = links[j] + 1)
continue;
if (j == i + 1) {
links[i] = i;
} else {
links[i] = links[i + 1];
links[i + 1] = links[j];
links[j] = i;
}
}
return links;
}
return NULL;
}
【问题讨论】:
-
MIXAL 代码的
09行不应该是LDA INPUT,1(KEY)吗? -
对于阅读本文的其他人,K 和 L 共享相同的地址空间。 K 存储在 (0:3) 中,即符号位和内存字的高 3 字节。 L 存储在 (4:5) 中,即内存字的低 2 字节。
标签: c insertion-sort knuth taocp