1、编写一个函数,用于计数一个单链表的节点个数,它的唯一参数是一个指向链表第一个节点的指针,编写这个函数时,你必须知道哪些信息?这个函数还能用于执行其他任务吗?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list{
int data;
struct list *next;
} List;
List *create_list(int count);
int list_count(List *head);
void main()
{
static List *head;
head = create_list(10);
if (head == NULL)
printf("Create list fail.\n");
else {
printf("Create list seccess.\n");
printf("list count: %d\n", list_count(head));
}
}
List *create_list(int count)
{
int i;
List *head;
List *next;
if (count <= 0)
return NULL;
head = malloc(sizeof(List));
if (head == NULL)
return NULL;
head->data = 5;
next = head;
for (i = 1; i < count; i++) {
next->next = malloc(sizeof(List));
next = next->next;
if (next == NULL)
return NULL;
next->data = 5 * (i + 1);
}
next = NULL;
return head;
}
int list_count(List *head)
{
int count = 0;
while (head != NULL) {
count++;
head = head->next;
}
return count;
}
2、编写一个函数,在一个无序的单链表中寻找一个特定的值,并返回一个指向该节点的指针。你可以假设节点数据结构在头文件singly_linked_list_node.h中定义。如果想让这个函数适用于有序的单链表,需不需要对它做些修改?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list{
int data;
struct list *next;
} List;
List *create_list(int count);
List *seek_list(List *head, int data);
void main()
{
static List *head;
static List *seek;
head = create_list(10);
if (head == NULL)
printf("Create list fail.\n");
else {
printf("Create list seccess.\n");
}
seek = seek_list(head, 15);
if (seek == NULL)
printf("seek list fail.\n");
else {
printf("seek list seccess.\n");
printf("seek data: %d\n", seek->data);
}
}
List *create_list(int count)
{
int i;
List *head;
List *next;
if (count <= 0)
return NULL;
head = malloc(sizeof(List));
if (head == NULL)
return NULL;
head->data = 5;
next = head;
for (i = 1; i < count; i++) {
next->next = malloc(sizeof(List));
next = next->next;
if (next == NULL)
return NULL;
next->data = 5 * (i + 1);
}
next = NULL;
return head;
}
List *seek_list(List *head, int data)
{
while (head != NULL) {
if (head->data == data)
return head;
head = head->next;
}
return NULL;
}
3、重新编写程序12.7的dll_list函数,使头和尾指针分别以一个单独的指针传递给函数,而不是作为一个节点的一部分,从函数的逻辑而言,这个改动有何效果?
int dll_insert(register Node *rootp, int value)
{
register Node *this;
register Node *next;
register Node *newnode;
for(this = rootp; (next = this->fwd) != NULL; this = next){
if(next->value == value)
return 0;
if(next->value > value)
break;
}
newnode = (Node *)malloc(sizeof(Node));
if(newnode == NULL)
return -1;
newnode->value = value;
newnode->fwd = next;
this->fwd = newnode;
if(this != rootp)
newnode->bwd = this;
else
newnode->bwd = NULL;
if(next != NULL)
next->bwd = newnode;
else
rootp->bwd = newnode;
return 1;
}
4、编写一个函数,反序排列一个单链表中所有的节点。函数应该具有下面的原型:
struct NODE *sll_reverse(struct NODE *first);
在头文件singly_linked_list_node.h中声明节点数据结构。函数的参数指向链表的第一个节点。当链表被重排之后,函数返回一个指向链表新头节点的指针,链表最后一个节点的link字段的值应设置为NULL,在空链表(first = = NULL)上执行这个函数将返回NULL。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list{
int data;
struct list *next;
} List;
List *create_list(int count);
List *sll_reverse(List *head);
void print_list(List *head);
void main()
{
static List *head;
static List *reverse;
head = create_list(10);
if (head == NULL)
printf("Create list fail.\n");
else {
printf("Create list seccess.\n");
}
reverse = sll_reverse(head);
if (reverse == NULL)
printf("reverse list fail.\n");
else {
printf("reverse list seccess.\n");
print_list(reverse);
}
}
List *create_list(int count)
{
int i;
List *head;
List *next;
if (count <= 0)
return NULL;
head = malloc(sizeof(List));
if (head == NULL)
return NULL;
head->data = 5;
next = head;
for (i = 1; i < count; i++) {
next->next = malloc(sizeof(List));
next = next->next;
if (next == NULL)
return NULL;
next->data = 5 * (i + 1);
}
next = NULL;
return head;
}
List *sll_reverse(List *head)
{
List *current;
List *next;
if (head == NULL)
return NULL;
for (current = NULL; head != NULL; head = next) {
next = head->next;
head->next = current;
current = head;
}
return current;
}
void print_list(List *head)
{
List *next;
printf("list: %d", head->data);
next = head->next;
while (next != NULL) {
printf("->%d", next->data);
next = next->next;
}
printf("\n");
}
5、编写一个程序,从一个单链表中移除一个节点,函数的原型如下:
int sll_remove(struct NODE **rootp, struct NODE *node);
你可以假设节点数据结构在头文件singly_linked_list_node.h中定义,函数的第一个参数是一个指向链表根指针的指针,第二个参数是一个指向欲移除的节点的指针,如果链表并不包含该指针,函数就返回假,否则它就移除这个节点并返回真,把一个欲移除的节点的指针而不是欲移除的值作为参数传递给函数有哪些优点?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list{
int data;
struct list *next;
} List;
List *create_list(int count);
int sll_remove(List **head, List *node);
void print_list(List *head);
void main()
{
static List *head;
List *remove;
head = create_list(10);
if (head == NULL)
printf("Create list fail.\n");
else {
printf("Create list seccess.\n");
}
//remove = head;
remove = head->next->next;
if (sll_remove(&head, remove)) {
printf("remove list seccess.\n");
print_list(head);
}
else
printf("remove list fail.\n");
}
List *create_list(int count)
{
int i;
List *head;
List *next;
if (count <= 0)
return NULL;
head = malloc(sizeof(List));
if (head == NULL)
return NULL;
head->data = 5;
next = head;
for (i = 1; i < count; i++) {
next->next = malloc(sizeof(List));
next = next->next;
if (next == NULL)
return NULL;
next->data = 5 * (i + 1);
}
next = NULL;
return head;
}
int sll_remove(List **head, List *node)
{
List *current;
if (node == NULL)
return 0;
while ((current = *head) != NULL) {
if (current == node) {
*head = current->next;
free(node);
return 1;
}
head = ¤t->next;
}
return 0;
}
void print_list(List *head)
{
List *next;
printf("list: %d", head->data);
next = head->next;
while (next != NULL) {
printf("->%d", next->data);
next = next->next;
}
printf("\n");
}
6、编写一个程序,从双链表中移除一个节点,函数的原型如下
int dll_remove(struct NODE *rootp, struct NODE *node);
你可以假设节点数据结构在头文件double_linked_list_node.h文件中定义,函数第一个参数是一个指向包含链表根指针的节点的指针(和程序12.7相同),第二个参数是个指向欲移除的节点的指针,如果链表并不包含欲移除的指针,函数就返回假,否则函数移除该节点并返回真。
int dll_remove(struct NODE *rootp, struct NODE *node)
{
struct NODE *current;
if (rootp == NULL || node == NULL)
return 0;
current = rootp->fwd;
while (current != NULL) {
if (current == node) {
if (current == rootp->fwd) {
rootp->fwd = current->fwd;
current->fwd->bwd = NULL;
}
else {
current->fwd->bwd = current->bwd;
}
if (current == rootp->bwd) {
rootp->bwd = current->bwd;
current->bwd->fwd = NULL;
}
else {
current->bwd->fwd = current->fwd;
}
free(node);
return 1;
}
current = current->fwd;
}
return 0;
}
7、编写一个函数,把一个新单词插入到问题7所描述的索引表中。函数接受两个参数,一个指向list指针的指针和一个字符串,该字符串假定包含单个单词,如果这个单词原先并未存在索引表中,它应该复制一块动态分配的节点并插入到这个索引表中,如果成功插入返回真,如果该字符原先已经存在于索引表中,或字符串不是以字符开头或其他错误返回假。函数应该维护一个一级链表,节点的排序以字母为序,其余的二级链表则以单词为序排列。
int insert_index(struct LIST **listp, char *word)
{
int i;
struct LIST *index;
struct WORD_LIST *current;
if (*listp == NULL || word == NULL)
return 0;
if (!islower(*word))
return 0;
index = *listp;
while (index != NULL) {
if (index->grapheme == *word)
break;
index = index->next;
}
current = index->word_list;
while(current->next != NULL) {
if (strcmp(current->word, word) == 0)
return 0;
current = current->next;
}
current->next = malloc(sizeof(struct WORD_LIST));
if (current->next == NULL)
return NULL;
current->next->word = word;
current->next->next = NULL;
return 1;
}