/*=== 下面是对队列而言可复用的链表处理函数 ===*/
void * CreateData1 ( void * data )
{
return ( NULL );
}
int DeleteData1 ( void * data )
{
/*NodeData1包括一个整型数据和一个指针,delete时整型数据会自动回收,
* 而string类型的字符串必须手动回收。
*/
free ( ((pND1) data)->text );
return ( 1 );
}
/*---------------------------------------------------------------
* 该方法根据返回值来确定当我们插入一个已经存在相同数据的节点时的操作,
* 在当前情况下,需要对单词计数,如果发现一个重复的单词,就将计数器+1;
* 0 发生错误
* 1 删除重复节点
* 2 插入重复节点
*-------------------------------------------------------------*/
int DuplicatedNode1 ( Link new_node,Link list_node )
{
return 2;
}
/* 只比较队列数据域中的优先级字段 */
int NodeDataCmp1 ( void *first, void*second )
{
return ( ( ((pND2)first)->priority -
((pND2) second)->priority));
}
/*=== 下面是对free list 节点的处理函数 ===*/
/* 数据域包括int的优先级和string类型的text */
void * CreateData2 ( struct NodeData1 *new_data )
{
new_data = malloc ( sizeof ( struct NodeData1 ));
if ( new_data == NULL )
return ( NULL );
/* 对相应的数据域赋初值,注意priority初始值为0*/
new_data->priority = 0;
new_data->text = (char *) malloc ( TEXT_SIZE + 1);
if ( new_data->text == NULL ) /* error copying string */
{
free ( new_data );
return ( NULL );
}
else
return ( new_data ); /* return a complete structure */
}
int DeleteData2 ( void * data )
{
/*在当前情况下,NodeData2包括一个指针,必须手动free */
free ( ((pND2) data)->text );
return ( 1 );
}
/* 插入一个重复节点 */
int DuplicatedNode2 ( Link new_node,Link list_node )
{
return 2;
}
/* this function is never called */
int NodeDataCmp2 ( void *first, void*second )
{
return ( 0 );
}
/* 复制数据 */
int DataCopy ( void * dest, void * src)
{
pND2 s, d; /* 新建两个节点用以复制 src --> dest*/
s = src;
d = dest;
if ( dest == NULL || src == NULL )
return ( 0 );
printf ( "About to copy %d - %s \n", /* 输出复制结果 */
s->priority, s->text );
d->priority = s->priority;
strncpy ( d->text, s->text, TEXT_SIZE );
return ( 1 );
}
1. QDRIVER.c
/*--- qdriver.c--------------------------- Listing 2-11 --------
* 从文件中读入数据,文件中包含类似于X9Message的数据行,其中 X = A,
* 则表示插入链表队列中,D则表示出队,P表示输出。 9表示队列项目的优先级;
* message表示队列的文本string;注意D和P可以单独给出,无需参数。
* 当每个动作被触发之后,输出状态信息。
*-------------------------------------------------------------*/
/*--- 开始处理文件---*/
/*temp->priority 默认为0,text为NULL,因此出队出队首元素*/
temp = CreateData2 ( NULL );
if ( temp == NULL )
{
fprintf ( stderr, "Error creating temporary data area\n" );
exit ( EXIT_FAILURE );
}
while ( fgets ( record, 64, fin ) != NULL )
{
if ( strlen ( record ) > 0 )
record[strlen ( record ) - 1] = 0; /*逐行读入原始数据,并处理末尾的换行符*/
if ( *record == 'A' ) /* add */
{
((pND2)temp)->priority = *(record + 1 ) - '0'; /*存储优先级(0-9)*/
((pND2)temp)->text = record +2; /*存储text文本*/
if ( enqueue ( queue, free_list,temp ) == 0 ) /*插入失败*/
{
printf ( "Error enqueueing%d %s\n",
((pND2)temp)->priority,
((pND2)temp)->text);
exit ( EXIT_FAILURE );
}
else
{
printf ( "Enqueued%d %s\n", /*插入成功*/
((pND2)temp)->priority,
((pND2)temp)->text);
if ( queue->LCount == 0) /*输出队列内容*/
printf ( "Empty queue\n" );
else
{
Link curr;
printf ( "--------List so far-------\n" );
for ( curr =queue->LHead;
curr != NULL;
curr = curr->next )
printf ( "%d%s\n",
((pND2)(curr->pdata))->priority,
((pND2)(curr->pdata))->text );
}
}
}
else
if ( *record == 'D' ) /* delete*/
{
if ( dequeue ( queue, free_list,temp ) == 0 ) /*出队失败*/
{
printf ( "Error dequeueing%d %s\n",
((pND2)temp)->priority,
((pND2)temp)->text);
return ( EXIT_FAILURE );
}
else /*出队成功,输出出队节点信息*/
printf ( "Dequeued %d%s\n",
((pND2)temp)->priority,
((pND2)temp)->text);
}
else
if ( *record == 'P' ) /* print*/
{
if ( queue->LCount == 0 ) /*空表,输出失败*/
printf ( "Emptyqueue\n" );
else
{
Link curr;
printf ( "\n-------- Listso far-------\n" );
for ( curr = queue->LHead;
curr != NULL;
curr = curr->next )
printf ( "%d %s\n",
((pND2)(curr->pdata))->priority,
((pND2)(curr->pdata))->text );
}
}
else
fprintf ( stderr, "Data error:%s\n", record );
}
fclose ( fin );
return ( EXIT_SUCCESS );
}
/*---------------------------------------------------------------
* enqueue入队方法,首先将数据利用插入到free list中。接着根据优先级插入
* 到队列中
*-------------------------------------------------------------*/
int enqueue ( struct List *lqueue,struct List *lfree,
void *new_entry )
{
Link curr, new_node;
/* Are there any free nodes left? */
if ( lfree->LCount == 0 ) /* 如果freelist是空表,就输出错误信息 */
{
fprintf ( stderr, "Exceeded maximum queue size\n" );
return ( 0 );
}
/* load the data into the head of the free list */
new_node = lfree->LHead; /*new_node指向lfree的头结点*/
if ( DataCopy ( new_node->pdata, new_entry ) == 0 ) /*将带插入节点的信息复制到头结点的数据域中*/
return ( 0 );
/* adding to an empty list? */
if ( lqueue->LCount == 0 ) /*如果是空队列lqueue*/
{
lfree->LHead = lfree->LHead->next;
/*将lfree表的头结点指针指向当前头结点指针的next,从lfree中“删除”该节点 */
new_node->prev = NULL;
new_node->next = NULL; /*将new_node的pre next指针置空*/
/*因为当前lqueue队列是空队列,添加一个节点需要将头尾指针都指向自身*/
lqueue->LTail = new_node;
lqueue->LHead = new_node;
/*添加成功后,lqueue计数器为1,lfree计数器减一*/
lqueue->LCount = 1;
lfree->LCount -= 1;
return ( 1 );
}
else
/* 若lqueue不是空队列,那么就遍历队列以找到插入位置 */
for ( curr = lqueue->LHead; ; curr = curr->next )
{
if ( curr == NULL /* 遍历至队尾 */
|| /* 或者找到了插入位置 */
NodeDataCmp1 ( new_entry,curr->pdata ) < 0 )
{
new_node = lfree->LHead;
lfree->LHead =lfree->LHead->next;
if ( curr == NULL ) /* 如果插入位置是队尾,插入new_node */
{
new_node->prev =lqueue->LTail;
new_node->next = NULL;
new_node->prev->next =new_node;
lqueue->LTail = new_node;
}
else
{
if ( curr->prev == NULL) /*如果插入位置是队头 */
lqueue->LHead =new_node; /*先将lqueue的头指针指向待插节点*/
new_node->prev =curr->prev;
new_node->next = curr; /*插入new_node*/
if ( curr->prev != NULL)
/*如果插入位置不是队头,将curr的前一个节点的next指针指向new_node*/
curr->prev->next =new_node;
curr->prev = new_node;
}
lqueue->LCount += 1;
/* update the free list */
lfree->LCount -= 1;
return ( 1 );
}
/*输出逐一按优先级查找的过程*/
else
{
pND2 p1, p2;
p1 = curr->pdata;
p2 = new_entry;
printf ( "searched at %d %s toinsert %d %s\n",
p1->priority,p1->text,
p2->priority,p2->text );
}
}
}
/*---------------------------------------------------------------
* 出队方法需要一个指向队头数据域的指针。它将从队列中移除的数据移入到free list中。注意如果在下一个队列操作之前不再实用出队数据,这个数据将会丢失,如果你需要先将其保存下来。当发生错误时返回0
*-------------------------------------------------------------*/
int dequeue ( struct List *lqueue,struct List *lfree,
void * our_data )
{
Link dequeued_link;
/* 如果时空队,输出错误信息*/
if ( lqueue->LCount == 0 )
{
fprintf ( stderr, "Error dequeue from empty queue\n" );
return ( 0 );
}
/* 保存一下出队的数据 */
if ( DataCopy ( our_data, lqueue->LHead->pdata ) == 0 )
return ( 0 );
/* 出队 */
dequeued_link = lqueue->LHead;
lqueue->LHead = lqueue->LHead->next;
lqueue->LCount -= 1;
/* 将出队数据插入到 free list中*/
dequeued_link->prev = NULL;
dequeued_link->next = lfree->LHead;
lfree->LHead = dequeued_link;
lfree->LCount += 1;
return ( 1 );
}