C和指针 第十二章 结构体 习题

12.3 重新编写12.7,使用头和尾指针分别以一个单独的指针传递给函数,而不是作为一个节点的一部分

#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0

//指针fwd指向前一个节点,bwd指向后一个节点
typedef struct NODE {
    struct NODE *fwd;
    struct NODE *bwd;
    int value;
} Node;

/*传入指向 头部和尾部节点的指针 的指针,四种情况
 * 插入到表头,
 * 插入到表尾,
 * 插入到空表中,
 * 插入到表中,前三个都需要修改headPtr或tailPtr指针
 */
int doubleLinklistInsert(Node **headPtr, Node **tailPtr, int value)
{
    Node *this = *headPtr;
    Node *newNode;

    while( this != NULL && this -> value < value){
        this = this -> fwd;
    }

    newNode = (Node *)malloc(sizeof(Node));
    newNode -> value = value;

    if(this == NULL){
    //插入到表尾,或者空表中
        if(this == *headPtr){
        //插入到空表
            *headPtr = newNode;
            *tailPtr = newNode;
            newNode -> fwd = NULL;
            newNode -> bwd = NULL;
        }else{
        //插入到表尾
            newNode -> fwd = NULL;
            //原来的表尾元素为当前节点的前节点
            newNode -> bwd = *tailPtr;
            (*tailPtr) -> fwd = newNode;
            //更新尾节点指针
            *tailPtr = newNode;
        }
    }else{
    //插入到表头,或者表中
        if(this == *headPtr){
            //插入到表头
            newNode -> bwd = NULL;
            //原来的表头变成第二个节点
            newNode -> fwd = *headPtr;
            (*headPtr) -> bwd = newNode;
            //更新表头
            *headPtr = newNode;
        }else{
            //插入到非空表中this位置的前面
            newNode -> fwd = this;
            newNode -> bwd = this -> bwd;
            this -> bwd -> fwd = newNode;
            this -> bwd = newNode;
        }
    }

    return TRUE;
}

int main()
{
    Node third;
    Node second;
    Node first;

    third = (Node){NULL, &second, 4};
    second = (Node){&third, &first, 2};
    first = (Node){&second, NULL, 1};

    Node *head = &first;
    Node *tail = &third;

    doubleLinklistInsert(&head, &tail, 35);
    doubleLinklistInsert(&head, &tail, 3);
    doubleLinklistInsert(&head, &tail, -10);

    Node *rootPtr = head;
    while(rootPtr != NULL){
        printf("%d\t", rootPtr -> value);
        rootPtr = rootPtr -> fwd;
    }
    return 0;
}

  运行:

12.4 编写函数反序排列单链表所有节点。

#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0

typedef struct Node {
    struct Node *next;
    int value;
} Linklist;

Linklist *sll_reverse(Linklist *first)
{
    if(first == NULL){
        return  NULL;
    }

    Linklist *current = first;
    Linklist *next;
    Linklist *pre;
    Linklist *morePre = NULL;

    while((next = current -> next) != NULL){
        //循环移动当前指向的节点
        pre = current;
        current = next;
        //修改前一节点的next指针为前前节点
        pre -> next = morePre;
        //移动前前节点morePre的指针
        morePre = pre;
    }

    //如果为单个节点之间返回
    if(current == first){
        return  first;
    }else{
    //修改最后一个节点的指针,作为头指针返回原来的最后一个节点的位置
        current -> next = pre;
        return current;
    }
}

int main()
{
    Linklist third = {NULL, 4};
    Linklist second = {&third, 3};
    Linklist first = {&second, 2};
    Linklist *head = &first;

    head = sll_reverse(head);

    while (head != NULL){
        printf("%d\t", head -> value);
        head = head -> next;
    }
    return 0;
}

  运行:

12.5 编写程序,从一个单链表中删除一个节点,第一个参数为指向链表头部的指针的指针

#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0

typedef struct Node {
    struct Node *next;
    int value;
} Linklist;

//从first指向的链表中删除节点node
int sll_delete(Linklist **first, Linklist *node)
{
    Linklist **ptr = first;
    //Ptr为指向 next字段的 指针
    while(*ptr != NULL && *ptr != node){
        ptr = &((*ptr) -> next);
    }
    //如果没有找到
    if(*ptr == NULL){
        return FALSE;
    }else{
    //如果找到了,变更前节点指向
        *ptr = (*ptr) -> next;
    //释放节点内存
        free(*ptr);     return FALSE;
    }
}

int main()
{
    Linklist third = {NULL, 3};
    Linklist second = {&third, 2};
    Linklist first = {&second, 1};
    Linklist *headPtr = &first;

    Linklist *head = headPtr;
    while (head != NULL){
        printf("%d\t", head -> value);
        head = head -> next;
    }
    printf("\n");

    sll_delete(&headPtr, &second);
    head = headPtr;
    while (head != NULL){
        printf("%d\t", head -> value);
        head = head -> next;
    }
    printf("\n");

    sll_delete(&headPtr, &first);
    head = headPtr;
    while (head != NULL){
        printf("%d\t", head -> value);
        head = head -> next;
    }
    printf("\n");

    sll_delete(&headPtr, &third);
    head = headPtr;
    while (head != NULL){
        printf("%d\t", head -> value);
        head = head -> next;
    }
    return 0;
}

  

运行:

12.6 双链表中移除节点,第一个参数为指向链表头部的指针,

#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0

typedef struct Node {
    struct Node *next;
    int value;
} Linklist;

//从first指向的链表中删除节点node
int sll_delete(Linklist *first, Linklist *node)
{
    Linklist *pre = NULL;
    Linklist *cur = first;

    while(cur != NULL && cur != node){
        pre = cur;
        cur = cur -> next;
    }

    //如果没有找到
    if(cur == NULL){
        return FALSE;
    }else if(cur == first){
        //此时first是传值传入,只可以修改头指针指向的值,修改为第二个节点
        *first = *(cur -> next);
        free(node);
        return TRUE;
    }else{
        pre -> next = cur -> next;
        free(node);
        return TRUE;
    }
}

int main()
{
    Linklist third = {NULL, 3};
    Linklist second = {&third, 2};
    Linklist first = {&second, 1};
    Linklist *headPtr = &first;

    Linklist *head = headPtr;
    while (head != NULL){
        printf("%d\t", head -> value);
        head = head -> next;
    }
    printf("\n");

    sll_delete(headPtr, &second);
    head = headPtr;
    while (head != NULL){
        printf("%d\t", head -> value);
        head = head -> next;
    }
    printf("\n");

    sll_delete(headPtr, &first);
    while (headPtr != NULL){
        printf("%d\t", headPtr -> value);
        headPtr = headPtr -> next;
    }
    printf("\n");

    sll_delete(headPtr, &third);
    head = headPtr;
    while (head != NULL){
        printf("%d\t", head -> value);
        head = head -> next;
    }
    printf("\n");
    return 0;
}

运行:

12.7 建立单词索引表

时间: 2024-08-26 10:51:10

C和指针 第十二章 结构体 习题的相关文章

C和指针 第十二章 结构体 整体赋值 error: expected expression

定义结构体后整体赋值时发生错误 typedef struct NODE { struct NODE *fwd; struct NODE *bwd; int value; } Node; //声明变量 Node first; first = {NULL, &second, 4}; 错误: error: expected expression 之所以不行是,{}内容被当做语句块了,c语言允许直接对结构体初始化,或者在赋值的时候加上类型说明,或者是逐一赋值. 初始化赋值: typedef struct

C和指针 第十二章 使用结构和指针

链表是一种常用的数据结构,每个节点通过链或者指针链接在一起,程序通过间接指针访问链表中的节点. typedef struct Node { //指向下一个节点的指针 struct Node *next; int value; } 单链表只可以单向遍历 单链表中插入:第一版 #include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 typedef struct Node { struct Node *n

C和指针 (pointers on C)——第十二章:使用结构和指针

第十二章 使用结构和指针 这章就是链表.先单链表,后双向链表. 总结: 单链表是一种使用指针来存储值的数据结构.链表中的每个节点包含一个字段,用于指向链表的下一个节点. 有一个独立的根指针指向链表的第1个节点.单链表只能从一个方向遍历. 如何insert单链表:1.新节点的link字段必须设置为指向它的后面节点.2.前一个节点的link字段必须指向这个新节点. 为了防止可能会插入链表的起始位置这种情况,在C中,可以保存一个指向必须进行修改的link字段的指针,而不是保存一个指向前一个节点的指针.

C和指针 (pointers on C)——第十二章:利用结构和指针

第十二章 利用结构和指针 这章就是链表.先单链表,后双向链表. 总结: 单链表是一种使用指针来存储值的数据结构.链表中的每一个节点包括一个字段,用于指向链表的下一个节点. 有一个独立的根指针指向链表的第1个节点. 单链表仅仅能从一个方向遍历. 怎样insert单链表:1.新节点的link字段必须设置为指向它的后面节点. 2.前一个节点的link字段必须指向这个新节点. 为了防止可能会插入链表的起始位置这样的情况,在C中,能够保存一个指向必须进行改动的link字段的指针.而不是保存一个指向前一个节

perl5 第十二章 Perl5中的引用/指针

第十二章 Perl5中的引用/指针 by flamephoenix 一.引用简介二.使用引用三.使用反斜线(\)操作符四.引用和数组五.多维数组六.子程序的引用  子程序模板七.数组与子程序八.文件句柄的引用 一.引用简介    引用就是指针,可以指向变量.数组.哈希表(也叫关联数组)甚至子程序.Pascal或C程序员应该对引用(即指针)的概念很熟悉,引用就是某值的地址,对其的使用则取决于程序员和语言的规定.在Perl中,可以把引用称为指针,二者是通用的,无差别的.引用在创建复杂数据方面十分有用

[CSAPP笔记][第十二章并发编程]

第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟悉的例子. 我们主要将并发看做是一种操作系统内核用来运行多个应用程序的机制. 但是,并发不仅仅局限于内核.它也可以在应用程序中扮演重要的角色. 例如 Unix信号处理程序如何允许应用响应异步事件 例如:用户键入ctrl-c 程序访问虚拟存储器的一个未定义的区域 其他情况 访问慢速I/O设备 当一个应

第十二章 并发编程 学习笔记

第十二章 并发编程 进程是程序级并发,线程是函数级并发. 三种基本的构造并发程序的方法: 进程:每个逻辑控制流是个一个进程,由内核进行调度和维护. I/O多路复用:应用程序在一个进程的上下文中显式地调度他们自己的逻辑流. 线程:运行在单一进程上下文中的逻辑流,由内核进行调度. 12.1 基于进程的并发编程 构造并发程序最简单的方法就是用进程. 使用大家都很熟悉的函数例如: fork exec waitpid 关于在父.子进程间共享状态信息:共享文件表,但不共享用户地址空间. 进程又独立的地址空间

C primer plus 第五版十二章习题

看完C prime plus(第五版)第十二章,随带完成了后面的习题. 1.不使用全局变量,重写程序清单12.4的程序. 先贴出12.4的程序,方便对照: 1 /* global.c --- 使用外部变量 */ 2 #include <stdio.h> 3 int units = 0; //一个外部变量 4 void critic(void); 5 int main(void) 6 { 7 extern int units; 8 9 printf ("How many pounds

JavaScript DOM编程艺术-学习笔记(第十二章)

第十二章 1.本章是综合前面章节的所有东西的,一个综合实例 2.流程:①项目简介:a.获取原始资料(包括文本.图片.音视频等) b.站点结构(文件目录结构) c.页面(文件)结构 ②设计(切图) ③css -  base.css用于引入使用的css文件 color.css  - 用于设置样式 layout.css - 用于设置布局 Typography.css - 用于设置版式 3.题外话:①在实际开发中,即使是一个空白项目也往往不会从一无所有做起,而借助的平台一般会提供目录结构,所以需要把自己