我的应用可以扫描来自v4l2
设备的频率并管理它们。
这有两个功能:
扫描函数并将找到的freq附加到GList * stations
:
typedef struct {
GList *stations;
} FreqScanData;
gboolean scan_cb (gpointer data)
{
static gfloat freq = FREQ_MIN - 4.0f/STEPS;
FreqScanData *fsd = data;
g_assert (fsd);
if (check_station (freq)) {
gfloat *f;
f = g_malloc (sizeof (gfloat));
*f = freq;
fsd->stations = g_list_append (fsd->stations, f);
}
freq += 1.0/STEPS;
return TRUE;
}
将freq
GList * stations
附加到现有列表GList * presets
的功能:
typedef struct {
{
GList *presets;
} Settings;
typedef struct Preset preset;
struct Preset
{
gchar *name;
gfloat freq;
};
void scan (void)
{
FreqScanData data;
Settings settings;
GList *node;
for (node = data.stations; node; node = node->next) {
preset *ps;
ps = g_malloc0 (sizeof (preset));
ps->name = g_strdup (_("unnamed"));
ps->freq = * ((gfloat *) node->data);
settings.presets = g_list_append (settings.presets, ps);
g_free (node->data);
}
}
我希望得到这方面的帮助:
如果<{strong> freq
找到并附加在data.stations
列表中已列入settings.presets
列表,则 不< / em>再次附加它们。
例如:
找到扫描站列表:87.50
92.20
101.50
104.50
106.60
和预设列表包含以下内容:
101.50
92.20
- &GT;不要在结果列表中复制它们
答案 0 :(得分:1)
正如Philip所说,使用哈希表(或树)可能会更好。那就是说,这不是你的问题(我认为,这就是为什么他在评论中建议而不是答案)。
如果您想继续使用链接列表,实际上只有两个选项:每次要插入数据时执行完整扫描,或者保持数据排序,完整扫描成为最差案例,但平均而言,你只需扫描列表的一半。
由于您使用的是g_list_append而不是g_list_prepend,因此您实际上已经进行了完整扫描。为了消除重复,你所要做的就是自己遍历列表直到你到达终点,检查每个值以查看频率是否等于你要插入的频率,如果是,则中止插入。但是,保持预设排序可能会更好,所以......
如果按列表对列表进行排序,则只需遍历列表,检查每个值以查看每个项目的频率是否等于您要插入的频率。如果是这样,则中止插入。如果不是,并且现有项目的频率大于您尝试插入的值,请在当前项目之前插入值。如果频率小于您尝试插入的值,请继续下一个项目。它看起来像这样:
static void preset_free (preset* ps)
{
g_free (ps->name);
g_free (ps);
}
static int preset_compare (preset* a, preset* b) {
if (a->freq < b->freq)
return -1;
else if (a->freq > b->freq)
return 1;
else
return 0;
}
static GList* insert_or_ignore_sorted (GList* list, preset* ps, GCompareFunc func) {
GList* cur = list;
int cmp_res;
for (; cur != NULL ; cur = cur->next) {
cmp_res = preset_compare ((preset*) cur->data, ps);
if (cmp_res == 0) {
preset_free (ps);
return;
}
if (cmp_res > 0)
break;
}
return g_list_insert_before (list, cur, ps);
}
void scan (FreqScanData* data)
{
Settings settings = { NULL };
GList *node;
for (node = data->stations; node; node = node->next) {
preset *ps;
ps = g_malloc0 (sizeof (preset));
ps->name = g_strdup (_("unnamed"));
ps->freq = * ((gfloat *) node->data);
settings.presets = insert_or_ignore_sorted (settings.presets, ps, (GCompareFunc) preset_compare);
g_free (node->data);
}
}