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 建立单词索引表

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define EXIST 1
#define NOEXIST 0
typedef struct Wordlist {
struct Wordlist *nextWord;
char *word;
} wordlist; typedef struct Alphalist {
struct Alphalist *nextAlpha;
//单个单词链表的指针
wordlist * wlPtr;
char alpha;
} alphalist; int isExist(wordlist *listPtr, char *string)
{
wordlist *current = listPtr; while(current != NULL){
if(strcmp(string, current -> word) == 0){
return EXIST;
}
current = current -> nextWord;
} return NOEXIST;
} int wordInsert(wordlist **listPtr, char *string)
{
wordlist **current = listPtr;
wordlist *new;
char *temp; while(*current != NULL){
//按字符排序进行插入
if(strcmp(string, (*current) -> word) < 0){
//生成new节点,插入到current之前,current为指向nextWord字段的指针
new = (wordlist *)malloc(sizeof(wordlist));
temp = (char *)malloc(strlen(string));
if(temp == NULL){
return FALSE;
}
strcpy(temp, string);
new -> word = temp;
//new指向 *current
new -> nextWord = *current;
//更新 *current为当前插入点
*current = new;
return TRUE;
}
//循环到下一点
current = &(*current) -> nextWord;
}
//循环玩整个列表后,还未找到,则末尾追加上
temp = (char *)malloc(strlen(string));
if(temp == NULL){
return FALSE;
}
strcpy(temp, string);
new = (wordlist *)malloc(sizeof(wordlist));
new -> word = temp;
new -> nextWord = NULL;
*current = new; return TRUE;
} int WordAlphaListInsert(alphalist *ptr, char *string)
{
char headCh = string[0];
alphalist *current = ptr;
wordlist *wl;
wordlist **rootPtr;
char *temp; //通过首字符查找wordlist
while (current -> alpha != headCh){
current = current -> nextAlpha;
} //已经存在
if(isExist(current -> wlPtr, string) == EXIST){
return FALSE;
}else{
//如果wordlist为NULL空,则创建初始单词链表
if(current -> wlPtr == NULL){
wl = (wordlist *)malloc(sizeof(wordlist));
//第一个节点,nextword为NULL
wl -> nextWord = NULL;
//申请内存拷贝字符串
temp = (char *)malloc(strlen(string));
if(temp == NULL){
return FALSE;
}
strcpy(temp, string);
wl ->word = temp;
current -> wlPtr = wl;
}else{
//如果有单词表,则插入单词
rootPtr = &(current -> wlPtr);
wordInsert(rootPtr, string);
}
return TRUE;
}
} //打印链表内容
void printList(alphalist *list)
{
alphalist *currentAl = list;
wordlist *currentWl;
while (currentAl != NULL){
printf("%c:\n", currentAl -> alpha);
currentWl = currentAl -> wlPtr;
while (currentWl != NULL){
printf("%s \t", currentWl -> word);
currentWl = currentWl -> nextWord;
}
printf("\n-----------------------\n");
currentAl = currentAl -> nextAlpha;
}
} int main()
{
char z;
alphalist *pre = NULL;
alphalist *current; //创建字母和单词列表
for(z = 122; z > 96; z--){
current = (alphalist *)malloc(sizeof(alphalist));
current -> alpha = z;
current -> wlPtr = NULL;
current -> nextAlpha = pre;
pre = current;
}
//插入单词
WordAlphaListInsert(current, "yang");
WordAlphaListInsert(current, "xun");
WordAlphaListInsert(current, "xan");
WordAlphaListInsert(current, "xzn");
WordAlphaListInsert(current, "wu");
WordAlphaListInsert(current, "ya");
WordAlphaListInsert(current, "yz");
printList(current); return 0;
}

运行:

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

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

    定义结构体后整体赋值时发生错误 typedef struct NODE { struct NODE *fwd; struct NODE *bwd; int value; } Node; //声明变量 ...

  2. C语言程序设计(十二) 结构体和共用体

    第十二章 结构体和共用体 当需要表示复杂对象时,仅使用几个基本数据类型显然是不够的 根本的解决方法是允许用户自定义数据类型 构造数据类型(复合数据类型)允许用户根据实际需要利用已有的基本数据类型来构造 ...

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

    链表是一种常用的数据结构,每个节点通过链或者指针链接在一起,程序通过间接指针访问链表中的节点. typedef struct Node { //指向下一个节点的指针 struct Node *next ...

  4. C和指针 第十二章 使用结构和指针 双链表和语句提炼

    双链表中每个节点包含指向当前和之后节点的指针,插入节点到双链表中需要考虑四种情况: 1.插入到链表头部 2.插入到链表尾部 3.插入到空链表中 4.插入到链表内部 #include <stdio ...

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

    第十二章 利用结构和指针 这章就是链表.先单链表,后双向链表. 总结: 单链表是一种使用指针来存储值的数据结构.链表中的每一个节点包括一个字段,用于指向链表的下一个节点. 有一个独立的根指针指向链表的 ...

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

    第十二章 Perl5中的引用/指针 by flamephoenix 一.引用简介二.使用引用三.使用反斜线(\)操作符四.引用和数组五.多维数组六.子程序的引用  子程序模板七.数组与子程序八.文件句 ...

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

    第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟 ...

  8. 《OpenCL异构并行编程实战》补充笔记散点,第五至十二章

    ▶ 第五章,OpenCL 的并发与执行模型 ● 内存对象与上下文相关而不是与设备相关.设备在不同设备之间的移动如下,如果 kernel 在第二个设备上运行,那么在第一个设备上产生的任何数据结果在第二个 ...

  9. PRML读书会第十二章 Continuous Latent Variables(PCA,Principal Component Analysis,PPCA,核PCA,Autoencoder,非线性流形)

    主讲人 戴玮 (新浪微博: @戴玮_CASIA) Wilbur_中博(1954123) 20:00:49 我今天讲PRML的第十二章,连续隐变量.既然有连续隐变量,一定也有离散隐变量,那么离散隐变量是 ...

随机推荐

  1. POJ1273Drainage Ditches[最大流]

    Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 71559   Accepted: 2784 ...

  2. Python 字符串

    Python访问字符串中的值 Python不支持单字符类型,单字符也在Python也是作为一个字符串使用. Python访问子字符串,可以使用方括号来截取字符串,如下实例: #!/usr/bin/py ...

  3. JavaScript中的this陷阱的最全收集 没有之一

    当有人问起你JavaScript有什么特点的时候,你可能立马就想到了单线程.事件驱动.面向对象等一堆词语,但是如果真的让你解释一下这些概 念,可能真解释不清楚.有句话这么说:如果你不能向一个6岁小孩解 ...

  4. Office2013插件开发Outlook篇(2)-- Ribbon

    一.获取当前实例 在Ribbon1的任何方法中调用如下代码,可获取当前实例. 如: Application application = new Application(); var list = ap ...

  5. RSA加密算法的java实现

    package rsa; import java.security.*;import java.security.interfaces.*;import javax.crypto.*; public ...

  6. 转载(sublime text 2 调试python时结果空白)

    sublime text 2 调试python时结果空白 之前用的时候都一切正常,今天突然就出现了这个问题.按ctrl+b执行的时候结果只有空白,查了很多文章都只提到了中文路径.系统路径等等,没有解决 ...

  7. Windows phone应用开发[18]-下拉刷新

    在windows phone 中采用数据列表时为了保证用户体验常遇到加载数据的问题.这个问题普遍到只要你用到数据列表就要早晚面对这个问题. 很多人会说这个问题已经有解决方案. 其实真正问题并不在于如何 ...

  8. JVM_垃圾回收串行、并行、并发算法(总结)

    一.串行 JDK1.5前的默认算法 缺点是只有一个线程,执行垃圾回收时程序停止的时间比较长 语法 -XX:+UseSerialGC 新生代.老年代使用串行回收 新生代复制算法 老年代标记-压缩 示例图 ...

  9. ES6新特性:使用export和import实现模块化

    在ES6前, 前端就使用RequireJS或者seaJS实现模块化, requireJS是基于AMD规范的模块化库,  而像seaJS是基于CMD规范的模块化库,  两者都是为了为了推广前端模块化的工 ...

  10. 理解Cookie和Session机制(转)

    目录[-] Cookie机制 什么是Cookie 记录用户访问次数 Cookie的不可跨域名性 Unicode编码:保存中文 BASE64编码:保存二进制图片 设置Cookie的所有属性 Cookie ...