合并N个有序链表与FQ公平调度

2018/05/09

Linux FQ实现

Linux内核在3.12版本引入了FQ这个Schedule，它的实现参照我的这篇文章：
Linux FQ 队列实现原理浅析 ：https://blog.csdn.net/dog250/article/details/80025939

Linux FQ的实现使用了红黑树来定义锚点，即所有的链表中 下一个要check 的节点都被维护在一棵红黑树中，这样做的目的是高效取出离当前节点最近的锚点进行check。

合并N个有序链表的基本思想

1. 尽量保持在当前链表向后遍历，直到当前链表下一个节点的key大于其它链表最小锚点的key；
2. 将当前节点的下一个节点作为一个锚点插入红黑树，从该最小锚点开始继续遍历，重复第1步。

合并N个有序链表的C语言实现

https://github.com/manuscola/rbtree

#include <stdio.h>
#include <stdlib.h>
#include"rbtree.h"

int a[] = {1,3,7,8,10,11,12,15,19,21,22,24,25,26};
int b[] = {0,4,5,6,9,16,17,18,27,30,31,32};
int c[] = {13,14,20,23,28,29};
int d[] = {2,33,100};

struct list {
struct list *next;
struct rbtree_node *node;
int v;
};

int compare(void* key_a,void* key_b)
{
int v_a = *(int *) (key_a);
int v_b = *(int *) (key_b);
if (v_a > v_b) {
return 1;
} else if (v_a == v_b) {
return 0;
}

return -1;
}

void merge(struct list *iter, struct rbtree* tree)
{
struct list *last = iter, *base = NULL;
struct rbtree_node *base_node = rbtree_min(tree);
// 取出最小的锚点并从红黑树中将其删除
if (base_node) {
base = (struct list *)base_node->data;
__rbtree_remove(base_node,tree);
}

if (!iter) {
return;
}
iter = iter->next;
// 一直遍历，直到next大于锚点
while (iter && (!base || iter->v < base->v)) {
last = iter;
iter = iter->next;
}
// 将next作为新的锚点加入红黑树
if (last->next) {
rbtree_insert(tree, &last->next->v, last->next);
}
// 递归重复
last->next = base;
merge(base, tree);
}

int main(int argc, char **argv)
{
int i = 0;
struct list *al = (struct list*)calloc(14, sizeof(*al));
struct list *bl = (struct list*)calloc(12, sizeof(*bl));
struct list *cl = (struct list*)calloc(6, sizeof(*cl));
struct list *dl = (struct list*)calloc(3, sizeof(*dl));
struct list *itera;
struct list *iterb;
struct list *iterc;
struct list *iterd;
struct list *base;

struct rbtree* tree = rbtree_init(compare);

// create 3 ordered-lists
{
for (i = 0; i < 14; i++) {
itera = &al[i];
itera->v = a[i];
itera->next = &al[i+1];
if (i == 0) {
rbtree_insert(tree, &itera->v, itera);
}
}
itera->next = NULL;

for (i = 0; i < 12; i++) {
iterb = &bl[i];
iterb->v = b[i];
iterb->next = &bl[i+1];
if (i == 0) {
rbtree_insert(tree, &iterb->v, iterb);
}
}
iterb->next = NULL;

for (i = 0; i < 6; i++) {
iterc = &cl[i];
iterc->v = c[i];
iterc->next = &cl[i+1];
if (i == 0) {
rbtree_insert(tree, &iterc->v, iterc);
}
}
iterc->next = NULL;

for (i = 0; i < 3; i++) {
iterd = &dl[i];
iterd->v = d[i];
iterd->next = &dl[i+1];
if (i == 0) {
rbtree_insert(tree, &iterd->v, iterd);
}
}
iterd->next = NULL;
}

// merge n sorted-lists
{
struct rbtree_node *node;

node = rbtree_min(tree);
__rbtree_remove(node,tree);

base = (struct list *)node->data;
merge(base, tree);
}

// print the result
{// 注意，从base开始遍历
for (; base; base=base->next) {
printf("%d %p\n", base->v, base);
}
}
}


• 3
点赞
• 11
收藏
觉得还不错? 一键收藏
• 3
评论
06-05 2860
03-08 8646
05-01 283
09-24 3440
04-08 4800
06-26 943
10-18 278
03-03 1547
01-14 849
08-01 154
10-12 628
09-27 132
10-26 678
09-25 587

“相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。