- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我最终认为我完成了创建一个有效的跳过列表并认为我应该检查我的工作并研究搜索功能的时间安排。我找到了一个关于如何使用 clock()
的教程并像这样实现它:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "skiplist.h"
int main() {
// initialize
SkipList *list = initSkipList();
// numbers to search for, array to store time
int n[] = {1, 10, 50, 100, 1000, 5000, 10000, 25000, 50000, 100000, 200000};
double time[11];
// insert
for (int i = 1; i <= 200000; i++)
insertElement(list, i);
// search, time, print
for (int i = 0; i < 11; i++) {
clock_t t;
t = clock();
findElement(list, n[i]);
t = clock() - t;
double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
ti[i] = time_taken;
printf("fun() took %f seconds to execute \n", time_taken);
}
return 0;
}
我想通过这样做并绘制 N 与时间的关系图,我会得到一个看起来对数的图形,但我的图形看起来是线性的:
我是否误解了我应该如何对我的函数进行计时以尝试测试时间复杂度,或者我的跳过列表只是没有按应有的方式进行搜索?这是我的整个跳过列表实现以防万一,但搜索函数称为 findElement()
:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#ifndef SKIPLIST_H_
#define SKIPLIST_H_
// number of lists
#define MAXLEVEL 5
// node with pointers
typedef struct Node {
int data;
struct Node *next[1]; // or C99 using flexible array members: *next[]
} Node;
// skiplist
typedef struct SkipList {
Node *header;
int level;
int count;
} SkipList;
// initialize skip list
SkipList* initSkipList() {
int i;
SkipList *list = calloc(1, sizeof(SkipList));
if (!list) {
printf("Memory Error\n");
exit(1);
}
//list->level = 0;
if ((list->header = calloc(1, sizeof(Node) + MAXLEVEL*sizeof(Node*))) == 0) {
printf("Memory Error\n");
exit(1);
}
for (i = 0; i <= MAXLEVEL; i++)
list->header->next[i] = list->header; // or = list->header?
printf("Skip list initialized.\n");
//srand(time(NULL));
return list;
}
// insert into skip list, return pointer to node
Node* insertElement(SkipList *list,int data) {
int i, newLevel;
Node* temp = list->header;
Node *update[MAXLEVEL+1];
// find where data belongs
for (i = list->level; i >= 0; i--) {
while(temp->next[i] != list->header && temp->next[i]->data < data)
temp = temp->next[i];
update[i] = temp;
}
temp = temp->next[0];
// if element already exists, just return it (no duplicates)
if (temp != list->header && temp->data == data)
return temp;
// determine level (coin flips till failure or max level reached)
for (newLevel = 0; (rand() < RAND_MAX/2) && (newLevel < MAXLEVEL); newLevel++); // Pr(4) == Pr(5)??
if (newLevel > list->level) {
for (i = list->level + 1; i <= newLevel; i++)
update[i] = list->header;
list->level = newLevel;
}
// make new node
if ((temp = calloc(1, sizeof(Node) + newLevel*sizeof(Node*))) == 0) {
printf("Memory Error\n");
exit(1);
}
temp->data = data;
list->count++;
// update next links
for (i = 0; i <= newLevel; i++) {
temp->next[i] = update[i]->next[i];
update[i]->next[i] = temp;
}
//printf("Element %d inserted into list. (level %d)\n", data, newLevel);
return temp;
}
// delete node containing data
void deleteElement(SkipList *list, int data) {
int i;
Node *update[MAXLEVEL+1], *temp;
temp = list->header;
for (i = list->level; i >= 0; i--) {
while (temp->next[i] != list->header && temp->next[i]->data < data)
temp = temp->next[i];
update[i] = temp;
}
// move to (possible) node to delete
temp = temp->next[0];
// if doesn't exist
if (temp == list->header || temp->data != data) {
printf("Element %d doesn't exist.\n", data);
return;
}
// adjust next pointers
for (i = 0; i <= list->level; i++) {
if (update[i]->next[i] != temp) break;
update[i]->next[i] = temp->next[i];
}
free (temp);
printf("Element %d deleted from list.\n", data);
list->count--;
// adjust header level
while ((list->level > 0) && (list->header->next[list->level] == list->header)) // double check
list->level--;
}
// find node containing data
Node* findElement(SkipList *list, int data){
int i;
Node *temp = list->header;
for (i = list->level; i >= 0; i--) {
while (temp->next[i] != list->header && temp->next[i]->data < data)
temp = temp->next[i];
}
temp = temp->next[0];
if (temp != list->header && temp->data == data) {
printf("Element %d found and returned.\n", data);
return (temp);
}
printf("Element %d not found.\n", data);
return 0;
}
/* Dynamic array for use in printSkipList() function */
typedef struct {
int *array;
size_t used;
size_t size;
} Array;
void initArray(Array *a, size_t initialSize) {
a->array = malloc(initialSize * sizeof(int));
a->used = 0;
a->size = initialSize;
}
void insertArray(Array *a, int element) {
if (a->used == a->size) {
a->size *= 2;
a->array = realloc(a->array, a->size * sizeof(int));
}
a->array[a->used++] = element;
}
void freeArray(Array *a) {
free(a->array);
a->array = NULL;
a->used = a->size = 0;
}
// print skip-list info and representational figure
void printSkipList(SkipList *list) {
int i, j, k, pos = 0, prevPos = 0, diff, numDigits;
Node* temp = list->header;
Array a;
// fill dynamic array with level 0 elements
initArray(&a, 10);
while (temp->next[0] != list->header) {
temp = temp->next[0];
insertArray(&a, temp->data);
}
temp = list->header;
// print number of levels
printf("\nNumber of levels in skip-list: %d\n", list->level + 1);
printf("Number of elements in skip-list: %d\n", list->count);
printf("Skip-list figure: \n");
// print data
for (i = list->level; i >= 0; i--) {
pos = 0, prevPos = 0;
while (temp->next[i] != list->header) {
numDigits = 0;
temp = temp->next[i];
while (temp->data != a.array[pos]) {
numDigits += floor (log10 (abs (a.array[pos]))) + 1;
pos++;
}
pos++;
diff = (pos - prevPos) - 1;
if (diff >= 1) {
for (j = 0; j < (4*diff)+numDigits; j++)
printf(" ");
}
printf("%d -> ", temp->data);
prevPos = pos;
}
temp = list->header;
printf("\n");
}
printf("\n\n");
}
#endif // SKIPLIST_H_
非常感谢任何建议,谢谢。
最佳答案
您的 MAXLEVEL 太小了。我认为原始论文的级别高达 lg(n),即列表大小的对数基数 2。
来自 Puch 1990 年的原始 skiplist 论文:
Determining MaxLevel
Since we can safely cap levels at L(n), we should choose MaxLevel = L(N) (where N is an upper bound on the number of elements in a skip list). If p = l/2, using MaxLevel = 16 is appropriate for data structures containing up to 2^16 elements
一般而言,如果 p 是 1/X,则使用列表大小的对数基数 X。
MAXLEVEL=5,我得到的结果和你看到的差不多。
evaitl@bb ~/se $ ./foo
Skip list initialized.
Element 1 found and returned.
fun() took 0.000014 seconds to execute
Element 10 found and returned.
fun() took 0.000002 seconds to execute
Element 50 found and returned.
fun() took 0.000002 seconds to execute
Element 100 found and returned.
fun() took 0.000002 seconds to execute
Element 1000 found and returned.
fun() took 0.000003 seconds to execute
Element 5000 found and returned.
fun() took 0.000004 seconds to execute
Element 10000 found and returned.
fun() took 0.000006 seconds to execute
Element 25000 found and returned.
fun() took 0.000011 seconds to execute
Element 50000 found and returned.
fun() took 0.000021 seconds to execute
Element 100000 found and returned.
fun() took 0.000044 seconds to execute
Element 200000 found and returned.
fun() took 0.000087 seconds to execute
将 MAXLEVEL 提高到 20,我得到:
evaitl@bb ~/se $ ./foo
Skip list initialized.
Element 1 found and returned.
fun() took 0.000016 seconds to execute
Element 10 found and returned.
fun() took 0.000003 seconds to execute
Element 50 found and returned.
fun() took 0.000003 seconds to execute
Element 100 found and returned.
fun() took 0.000002 seconds to execute
Element 1000 found and returned.
fun() took 0.000002 seconds to execute
Element 5000 found and returned.
fun() took 0.000003 seconds to execute
Element 10000 found and returned.
fun() took 0.000004 seconds to execute
Element 25000 found and returned.
fun() took 0.000003 seconds to execute
Element 50000 found and returned.
fun() took 0.000004 seconds to execute
Element 100000 found and returned.
fun() took 0.000003 seconds to execute
Element 200000 found and returned.
fun() took 0.000004 seconds to execute
将 400000 和 800000 添加到您的 n[]:
evaitl@bb ~/se $ ./foo
Skip list initialized.
Element 1 found and returned.
fun() took 0.000016 seconds to execute
Element 10 found and returned.
fun() took 0.000001 seconds to execute
Element 50 found and returned.
fun() took 0.000001 seconds to execute
Element 100 found and returned.
fun() took 0.000002 seconds to execute
Element 1000 found and returned.
fun() took 0.000002 seconds to execute
Element 5000 found and returned.
fun() took 0.000002 seconds to execute
Element 10000 found and returned.
fun() took 0.000002 seconds to execute
Element 25000 found and returned.
fun() took 0.000004 seconds to execute
Element 50000 found and returned.
fun() took 0.000003 seconds to execute
Element 100000 found and returned.
fun() took 0.000003 seconds to execute
Element 200000 found and returned.
fun() took 0.000003 seconds to execute
Element 400000 found and returned.
fun() took 0.000004 seconds to execute
Element 800000 found and returned.
fun() took 0.000003 seconds to execute
关于c - 我的跳过列表真的是在 N 而不是 log(N) 中搜索吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38535401/
我在我的应用程序中使用 Hibernate Search。其中一个子集合被映射为 IndexedEmbedded。子对象有两个字段,一个是 id,另一个是日期(使用日期分辨率到毫秒)。当我搜索 id=
The App Engine Search API有一个 GeoPoint 字段。可以用它来进行半径搜索吗?例如,给定一个 GeoPoint,查找位于特定半径内的所有文档。 截至目前,它看起来像 Ge
客户对我正在做的员工管理项目提出了这个新要求,以允许他们的用户进行自定义 bool 搜索。 基本上允许他们使用:AND、OR、NOT、括号和引号。 实现它的最佳方法是什么?我检查了 mysql,它们使
很想知道哪个更快 - 如果我有一个包含 25000 个键值对的数组和一个包含相同信息的 MySQL 数据库,搜索哪个会更快? 非常感谢大家! 最佳答案 回答这个问题的最好方法是执行基准测试。 关于ph
我喜欢 smartcase,也喜欢 * 和 # 搜索命令。但我更希望 * 和 # 搜索命令区分大小写,而/和 ?搜索命令遵循 smartcase 启发式。 是否有隐藏在某个地方我还没有找到的设置?我宁
我有以下 Marklogic 查询,当在查询控制台中运行时,它允许我检索具有管理员权限的系统用户: xquery version "1.0-ml"; import schema namespace b
我希望当您搜索例如“A”时,所有以“A”开头的全名都会出现。因此,如果名为“Andreas blabla”的用户将显示 我现在有这个: $query = "SELECT full_name, id,
我想在我的网站上添加对人名的搜索。好友列表已经显示在页面上。 我喜欢 Facebook 这样做的方式,您开始输入姓名,Facebook 只会显示与查询匹配的好友。 http://cl.ly/2t2V0
您好,我在我的网站上进行搜索时遇到此错误。 Fatal error: Uncaught Error: Call to undefined function mysql_connect() in /ho
声明( 叠甲 ):鄙人水平有限,本文为作者的学习总结,仅供参考。 1. 搜索介绍 搜索算法包括深度优先搜索(DFS)和广度优先搜索(BFS)这两种,从起点开始,逐渐扩大
我正在为用户列表使用 FuturBuilder。我通过 futur: fetchpost() 通过 API 获取用户。在专栏的开头,我实现了一个搜索栏。那么我该如何实现我的搜索栏正在搜索呢? Cont
我正在使用 MVC5,我想搜索结果并停留在同一页面,这是我在 Controller (LiaisonsProjetsPPController) 中执行搜索操作的方法: public ActionRes
Azure 搜索中的两种方法 Upload 与 MergeOrUpload 之间有什么区别。 他们都做完全相同的事情。即,如果文档不存在,它们都会上传文档;如果文档已经存在,则替换该文档。 由于这两种
实际上,声音匹配/搜索的当前状态是什么?我目前正在远程参与规划一个 Web 应用程序,该应用程序将包含和公开记录的短音频剪辑(最多 3-5 秒,人名)的数据库。已经提出了一个问题,是否可以实现基于用户
在商业应用程序中,具有数百个面并不罕见。当然,并非所有产品都带有所有这些标记。 但是在搜索时,我需要添加一个方面查询字符串参数,其中列出了我想要返回的所有方面。由于我事先不知道相关列表,因此我必须在查
当我使用nvcc 5.0编译.cu文件时,编译器会为我提供以下信息。 /usr/bin/ld: skipping incompatible /usr/local/cuda-5.0/lib/libcud
我正在使用基于丰富的 Lucene 查询解析器语法的 Azure 搜索。我将“~1”定义为距离符号的附加参数)。但我面临的问题是,即使存在完全匹配,实体也没有排序。 (例如,“blue~1”将返回“b
我目前有 3 个类,一个包含 GUI 的主类,我在其中调用此方法,一个包含数据的客户类,以及一个从客户类收集数据并将其放入数组列表的 customerList 类,以及还包含搜索数组列表方法。 我正在
假设我有多个 6 字符的字母数字字符串。 abc123、abc231、abc456、cba123、bac231 和 bac123 。 基本上我想要一个可以搜索和列出所有 abc 实例的选择语句。 我只
我有这个表 "Table"内容: +--------+ | Serial | +--------+ | d100m | <- expected result | D100M | <- expect
我是一名优秀的程序员,十分优秀!