(1)clist.h
/*****************************************************************************
* *
* ------------------------------- clist.h -------------------------------- *
* *
*****************************************************************************/
#ifndef CLIST_H
#define CLIST_H
#include <stdlib.h>
#include <string.h>
/*****************************************************************************
* *
* Define a structure for circular list elements. *
* *
*****************************************************************************/
typedef struct CListElmt_ {
void *data;
struct CListElmt_ *next;
} CListElmt;
/*****************************************************************************
* *
* Define a structure for circular lists. *
* *
*****************************************************************************/
typedef struct CList_ {
int size;
int (*match)(const void *key1, const void *key2);
void (*destroy)(void *data);
CListElmt *head;
} CList;
/*****************************************************************************
* *
* --------------------------- Public Interface --------------------------- *
* *
*****************************************************************************/
void clist_init(CList *list, void (*destroy)(void *data));
void clist_destroy(CList *list);
int clist_ins_next(CList *list, CListElmt *element, const void *data);
int clist_rem_next(CList *list, CListElmt *element, void **data);
#define clist_size(list) ((list)->size)
#define clist_head(list) ((list)->head)
#define clist_data(element) ((element)->data)
#define clist_next(element) ((element)->next)
/*****************************************************************************
* *
* ------------------------------- clist.c -------------------------------- *
* *
*****************************************************************************/
/*****************************************************************************
* *
* ------------------------------ clist_init ------------------------------ *
* *
*****************************************************************************/
void clist_init(CList *list, void (*destroy)(void *data)) {
/*****************************************************************************
* *
* Initialize the list. *
* *
*****************************************************************************/
list->size = 0;
list->destroy = destroy;
list->head = NULL;
return;
}
/*****************************************************************************
* *
* ---------------------------- clist_destroy ----------------------------- *
* *
*****************************************************************************/
void clist_destroy(CList *list) {
void *data;
/*****************************************************************************
* *
* Remove each element. *
* *
*****************************************************************************/
while (clist_size(list) > 0) {
if (clist_rem_next(list, list->head, (void **)&data) == 0 && list->destroy
!= NULL) {
/***********************************************************************
* *
* Call a user-defined function to free dynamically allocated data. *
* *
***********************************************************************/
list->destroy(data);
}
}
/*****************************************************************************
* *
* No operations are allowed now, but clear the structure as a precaution. *
* *
*****************************************************************************/
memset(list, 0, sizeof(CList));
return;
}
/*****************************************************************************
* *
* ---------------------------- clist_ins_next ---------------------------- *
* *
*****************************************************************************/
int clist_ins_next(CList *list, CListElmt *element, const void *data) {
CListElmt *new_element;
/*****************************************************************************
* *
* Allocate storage for the element. *
* *
*****************************************************************************/
if ((new_element = (CListElmt *)malloc(sizeof(CListElmt))) == NULL)
return -1;
/*****************************************************************************
* *
* Insert the element into the list. *
* *
*****************************************************************************/
new_element->data = (void *)data;
if (clist_size(list) == 0) {
/**************************************************************************
* *
* Handle insertion when the list is empty. *
* *
**************************************************************************/
new_element->next = new_element;
list->head = new_element;
}
else {
/**************************************************************************
* *
* Handle insertion when the list is not empty. *
* *
**************************************************************************/
new_element->next = element->next;
element->next = new_element;
}
/*****************************************************************************
* *
* Adjust the size of the list to account for the inserted element. *
* *
*****************************************************************************/
list->size++;
return 0;
}
/*****************************************************************************
* *
* ---------------------------- clist_rem_next ---------------------------- *
* *
*****************************************************************************/
int clist_rem_next(CList *list, CListElmt *element, void **data) {
CListElmt *old_element;
/*****************************************************************************
* *
* Do not allow removal from an empty list. *
* *
*****************************************************************************/
if (clist_size(list) == 0)
return -1;
/*****************************************************************************
* *
* Remove the element from the list. *
* *
*****************************************************************************/
*data = element->next->data;
if (element->next == element) {
/**************************************************************************
* *
* Handle removing the last element. *
* *
**************************************************************************/
old_element = element->next;
list->head = NULL;
}
else {
/**************************************************************************
* *
* Handle removing other than the last element. *
* *
**************************************************************************/
old_element = element->next;
element->next = element->next->next;
}
/*****************************************************************************
* *
* Free the storage allocated by the abstract data type. *
* *
*****************************************************************************/
free(old_element);
/*****************************************************************************
* *
* Adjust the size of the list to account for the removed element. *
* *
*****************************************************************************/
list->size--;
return 0;
}
#endif
(2)ex-1.c
/*****************************************************************************
* *
* ex-1.c *
* ====== *
* *
* Description: Illustrates using a circular list (see Chapter 5). *
* *
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "clist.h"
/*****************************************************************************
* *
* ------------------------------ print_list ------------------------------ *
* *
*****************************************************************************/
static void print_list(const CList *list) {
CListElmt *element;
int *data,
size,
i;
/*****************************************************************************
* *
* Display the circular list. *
* *
*****************************************************************************/
fprintf(stdout, "List size is %d (circling twice)\n", clist_size(list));
size = clist_size(list);
element = clist_head(list);
/*****************************************************************************
* *
* Iterate twice through the circular list to verify the circular links. *
* *
*****************************************************************************/
i = 0;
while (i < size * 2) {
data = clist_data(element);
fprintf(stdout, "list[%03d]=%03d\n", (i % size), *data);
element = clist_next(element);
i++;
}
return;
}
/*****************************************************************************
* *
* --------------------------------- main --------------------------------- *
* *
*****************************************************************************/
int main(int argc, char **argv) {
CList list;
CListElmt *element;
int *data,
i;
/*****************************************************************************
* *
* Initialize the circular list. *
* *
*****************************************************************************/
clist_init(&list, free);
/*****************************************************************************
* *
* Perform some circular list operations. *
* *
*****************************************************************************/
element = clist_head(&list);
for (i = 0; i < 10; i++) {
if ((data = (int *)malloc(sizeof(int))) == NULL)
return 1;
*data = i + 1;
if (clist_ins_next(&list, element, data) != 0)
return 1;
if (element == NULL)
element = clist_next(clist_head(&list));
else
element = clist_next(element);
}
print_list(&list);
element = clist_head(&list);
for (i = 0; i < 10; i++)
element = clist_next(element);
data = clist_data(element);
fprintf(stdout, "Circling and removing an element after the one containing "
"%03d\n",*data);
if (clist_rem_next(&list, element, (void **)&data) != 0)
return 1;
free(data);
print_list(&list);
element = clist_head(&list);
for (i = 0; i < 15; i++)
element = clist_next(element);
data = clist_data(element);
fprintf(stdout, "Circling and inserting 011 after the element containing "
"%03d\n", *data);
if ((data = (int *)malloc(sizeof(int))) == NULL)
return 1;
*data = 11;
if (clist_ins_next(&list, element, data) != 0)
return 1;
print_list(&list);
/*****************************************************************************
* *
* Destroy the circular list. *
* *
*****************************************************************************/
fprintf(stdout, "Destroying the list\n");
clist_destroy(&list);
return 0;
}
(3)page.h
/*****************************************************************************
* *
* -------------------------------- page.h -------------------------------- *
* *
*****************************************************************************/
#ifndef PAGE_H
#define PAGE_H
#include "clist.h"
/*****************************************************************************
* *
* Define a structure for information about pages. *
* *
*****************************************************************************/
typedef struct Page_ {
int number;
int reference;
} Page;
/*****************************************************************************
* *
* --------------------------- Public Interface --------------------------- *
* *
*****************************************************************************/
int replace_page(CListElmt **current);
/*****************************************************************************
* *
* ----------------------------- replace_page ----------------------------- *
* *
*****************************************************************************/
int replace_page(CListElmt **current) {
/*****************************************************************************
* *
* Circle through the list of pages until one is found to replace. *
* *
*****************************************************************************/
while (((Page *)(*current)->data)->reference != 0) {
((Page *)(*current)->data)->reference = 0;
*current = clist_next(*current);
}
printf("%d\n",*current);
return ((Page *)(*current)->data)->number;
}
#endif
(4)ex-2.c
/*****************************************************************************
* *
* ex-2.c *
* ====== *
* *
* Description: Illustrates second-chance page replacement (see Chapter 5). *
* *
*****************************************************************************/
#include <stdio.h>
#include "page.h"
int main(int argc, char **argv) {
CList list;
CListElmt *current;
Page *p;
int i;
/*****************************************************************************
* *
* Initialize the circular list. *
* *
*****************************************************************************/
clist_init(&list, free);
/*****************************************************************************
* *
* Load the pages into the list. *
* *
*****************************************************************************/
current = NULL;
for (i = 0; i < 10; i++) {
if ((p = (Page *)malloc(sizeof(Page))) == NULL)
return 1;
if (i < 5)
p->reference = 1;
else
p->reference = 0;
p->number = i;
if (clist_ins_next(&list, current, p) != 0)
return 1;
if (current == NULL)
current = clist_next(clist_head(&list));
else
current = clist_next(current);
}
current = clist_head(&list);
for (i = 0; i < 10; i++) {
p = clist_data(current);
fprintf(stdout, "p[%d].number=%d, p[%d].reference=%d\n", i, p->number, i,
p->reference);
current = clist_next(current);
}
/*****************************************************************************
* *
* Get the number of the page to replace. *
* *
*****************************************************************************/
current = clist_head(&list);
printf("%d\n",current);
//如果不使用双指针,那么传递给replace_page函数的参数是指针的地址拷贝
//函数运行完,current的值不会变化,使用双指针,current才会变化
i = replace_page(¤t);
fprintf(stdout, "Selected %d\n", i);
printf("%d\n",current);
//current = clist_head(&list);
for (i = 0; i < 10; i++) {
p = clist_data(current);
fprintf(stdout, "p[%d].number=%d, p[%d].reference=%d\n", i, p->number, i,
p->reference);
current = clist_next(current);
}
/*****************************************************************************
* *
* Destroy the circular list. *
* *
*****************************************************************************/
fprintf(stdout, "Destroying the list\n");
clist_destroy(&list);
return 0;
}