【问题标题】:Queue with linked list and counter in CC中的链表和计数器队列
【发布时间】:2013-04-06 19:16:28
【问题描述】:

我正在实现一个带有链表的队列,该链表将使用简单的命令在同一个程序中发送和接收数据,我想为队列中的每个数据添加一个计数器,值是新的,待处理或确认。那么我是将它存储在一个数组中还是有其他方式,因为计数器的数量会很大?

#define TOTALPACKETS 100
#define WINDOW   5
#define ACK      2
#define PENDING  1
#define NEW      0 


typedef int Item ;
typedef struct node *link;  
struct node{                
    Item data;
    Item status;
    link next; 
};

int QUEUEempty(link head){
    return head==NULL;
}

void QUEUEput(link *head, link *tail, Item data, Item status){
    if (*head==NULL){
                    (*tail)=(link)malloc(sizeof(node)); 
                    (*tail)->data=data;
                    (*tail)->next=NULL;
                (*tail)->status=NEW;
                    *head=*tail;
                    return;}
    (*tail)->next=(link)malloc(sizeof(node));
    *tail=(*tail)->next;
    (*tail)->data=data;
    (*tail)->next=NULL;
    (*tail)->status=NEW;
    return;
}

Item QUEUEget(link *head){
    Item data=(*head)->data;
    Item status
    link t=*head;
    *head=(*head)->next;
    free(t);
    return data; 
}

【问题讨论】:

  • 如果是队列,则使用链表。如果您的计数器非常大并且不能重复使用,也可以使用 long。
  • 欢迎来到 Stack Overflow。请尽快阅读FAQ。很难为您提供太多帮助,因为您没有显示任何您正在考虑使用的代码。链表是“侵入式”(指针是添加到列表中的结构的一部分)还是“非侵入式”(列表节点结构包括指向数据的指针)?如果它是侵入性的,则将计数器添加到结构中。如果它是非侵入式的,则从您的描述中不清楚计数器可能适合的位置——甚至计数器实际计数的内容。
  • 好的,我会尽量说得更清楚。(虽然我确实阅读了常见问题解答)。我需要一个计数器/指针添加到所使用的结构中,它将根据数据包在 send() 和 receive() 之后的哪个阶段取三个值之一(0 表示 NEW,1 表示 PENDING,2 表示 ACK)。我不不知道的是,如果在我将它添加到结构中之后,我将如何更改它?假设你把它写成 ptr->val = 0 或者你必须把每个计数器放在一个数组中才能做到这一点?

标签: c linked-list queue


【解决方案1】:

我喜欢认为我很擅长阅读字里行间和预测隐藏的意图,但我无法很好地了解你在追求什么。我会把它做成 cmets,除非有太多单词不能舒适地放入 cmets 并且格式非常有限。 (这不是一个真正的答案——这就是为什么它是 CW。)

您谈论的“计数器”具有三个值之一(NEW、PENDING、ACK)。这听起来更像是一种状态或状态,而不是计数器。

让我们尝试一些设计;你可以说这是哪里出了问题。这假设一个非侵入式队列设计。

typedef struct Data Data;   /* This is the data that you're queueing - details TBS */

typedef struct QNode
{
    Data  *data;
    QNode *next;
    QNode *prev;
    ...possibly other data...status?
} QNode;

typedef struct Queue
{
    QNode *head;
    QNode *tail;
    ...possibly other data...counts?
} Queue;

extern int q_add(Queue *q, Data *d);    // Add datum d to queue per policy
extern int q_next(Queue *q, Data **dp); // Remove next datum from queue per policy

现在,基于此大纲的系统至少可以在两个地方存储计数器或状态。一个地方将在struct Data 内,这是一种尚不透明的结构类型。另一个可能的地方是struct QNode。您也可以使用struct Queue 中的摘要计数器来密切关注每个州有多少节点,如果这是您所追求的。

以此为起点,你追求的是什么?在这一点上,一切都是可以改变的——但如果没有具体的东西可以进行,我们就无法提供更多帮助。

【讨论】:

  • 现在我有了我的电脑,我用代码编辑了第一篇文章。我想在单个程序中实现 SR 协议。我将继续发送我的窗口大小,并希望使用该状态计数器跟踪内部的每个数据包。 Send() 会将其从 NEW 或 PENDING 更改为 PENDING ,并且 receive() 会将 PENDING 更改为 ACK 或 PENDING。现在我不知道 το 如何在不丢失这两个函数的代码中的任何一个状态的情况下访问每个状态并更改它们的值。希望能帮助您理解。
  • “SR 协议”,如 'Selective Repeat Protocol'。我对您在评论中使用希腊语“如何访问”很感兴趣。我不喜欢包含指针的 typedef,例如 typedef struct node *link;,但我想这部分是个人风格(尽管许多其他程序员共享的风格偏好)。对于不透明类型(未取消引用以访问用户代码中的成员),它们很好。对于其他许多...好吧,假设(*tail)->next 等很冗长。我有link end = *tail; 然后end->next 等。这更容易理解。
  • 我正在思考问题中您更新的代码。这行(*tail)=(link)malloc(sizeof(node)); 仅在您的 C 编译器实际上是伪装的 C++ 编译器(换句话说,MSVC)时才编译。您还没有定义类型 node(虽然您已经定义了 struct node,但 C 不会自动创建类型 node,而 C++ 会)。
  • 您对 C++(我使用的是 Visual Studio 2008)和希腊语的看法可能是对的。现在讨论主题,所以我想它会自动创建节点。你的第一个答案让我有点失落(“还有很多……等等”),这只是个人陈述,对吧?那么如何向它添加状态?如果我使用我已经拥有的行 (*tail)->status=NEW; 并使用它来更改我每次将使用的每个数据包的状态,它是否有效?我想队列的尾巴是我要使用的那个?
  • (*head)->status=PENDING; 是我的意思。我想我会得到队列的头包而不是尾包。
【解决方案2】:

您的节点中已经有了状态“计数器”,但是(正如 Jonathan Leffler 建议的那样)让我们将其称为状态或状态。 在您的选择性重复 ARQ 协议实现的 ACKreceive() 中,存在使用随确认发送的序列号访问节点(不仅是状态,还包括数据,以防重传)的问题;我们必须遍历链表才能到达正确的节点,但是在这个遍历过程中我们还可以释放已确认的节点,所以这是无害的。

不过,您可以改进您的数据结构。我们不需要每个节点都有一个明确的状态变量,因为状态是严格排序的。从列表的头到尾,首先有零个(或更多仅当您不立即释放)ACK 节点,其次有零个或多个 PENDING 节点,最后有零个或多个 NEW 节点。因此,为了维护状态信息,指向第一个 NEW(也可能是第一个 PENDING)节点的索引或指针就足够了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多