C_数据结构_链表_及基础操作(返回值或二级指针双实现)

  • 链表是一种数据结构,是一种数据存放的方式
  • 链表是由结构体形成的,每个结构体内部有一个结构体指针指向下一个结构体,结构体的存储地址不连续
    -------------结构体A-----------              ------------结构体B-----------       
    |              |             |            \ |              |             |
    |     data     |     *next   |--------------|     data     |     *next	 |
    |              |             |            / |              |             |
    ------------------------------              ------------------------------
结构体A中的结构体指针NEXT存放了结构体B的地址

struct Node{
        int data;							//链表中元素数据
        struct Node *next;			//元素中存放下一个元素的地址
}*pNode,node ;
  • 将结构体中的结构体指针指向下一个同类型的结构体,直到链接所有的指定的结构体,这就是链表。最后一个元素中的指针指向NULL
		struct Node head = {1,&dot1};
        struct Node dot1 = {2,&dot2};
        struct Node dot2 = {3,&dot3};
        struct Node dot3 = {4,NULL};
  • 相对于数组,具有更加灵活的数据更改能力(包括增,减内部元素),只需要将NEXT指针指向指定的下一个结构体,后面顺序依然保持不变

链表遍历

因为链表每个元素中都有一个指向自己结构体类型的指针,且这个指针指向下一个元素。设一个该结构体指针sign指向头节点(第一个节点),对其操作完成后,sign指针指向头节点中的结构体指针指向的位置(sign指针移动到了下一个结点),以此类推,直到指针指向尾节点的next指针指向的NULL,遍历结束。

struct Node *sign = &head;
while(sign != NULL){
      printf("%d\t",sign->data);
      sign = sign->next;
}

*对链表的查找和节点统计也是相同道理

节点增加

节点的增加主要通过改变节点的结构体指针来实现,如下图下方节点B插入A,C节点之间

  1. 先将A中next指向的地址给B的next指针
  2. 再将A的next指向B节点
    两个语句的顺序不能改变
    在这里插入图片描述

后插

新节点加在指定节点后方,同样需要遍历链表,如当前节点是否是指定的节点,就将当前节点的next赋值给新节点的next,再将当前节点的next指向新节点

void insertNode(struct Node *p, struct Node *new, int position){                 
        while(p != NULL){
                if(p->data == position){
                        new->next = p->next;	//节点添加
                        p->next = new;
                        return;		
                }
                p=p->next;			//移动到下一个节点
        }
        assert(false);		//没有改节点,错误退出
        return;
}

前插

这是需要考虑,当添加位置是链表第一个节点时,此时需要更换链表的头节点,如下实验代码对头节点进行单独判断,这里犯了个错误,指针变量在函数中的改变,不会影响该变量在main中的指针变量(多思考理解)。为了改变指针,这里需要使用二级指针,将指针的地址传进来,再改变二级指针以至于指针改变,将头结点指针指向新的节点

//错误示范
void insertNode(pNode p, pNode new, int posit){                 
        if(posit == 1){
                new->next = p;
                return ;
        }
        while(p->next != NULL){
                if(p->next->data == posit){
                        new->next = p->next;
                        p->next = new;
                        return;
                }
                p=p->next;
        }
        puts("no such position for inserting! ");
        return;
}
二级指针实现

在main中定义一个指向头结点的指针phead,将其地址传递给函数。函数得到的是一个二级指针,指向一个指针,该指针指向节点,cur等价于head,方便理解。循环遍历整个链表,直至指向节点的指针指向空NULL(*cur != NULL;);
如果当前节点中的数据匹配,此时要将一个新的节点放当前节点前面,所以新节点的next存储当前节点的地址(new->next = *cur),重点是要让指向当前节点的指针指向新节点,因为使用的二级指针,所以取二级指针的内容就可以改动main中指向节点的指针了【这个指针等价于它前一个节点的next,因为上了一轮循环的最后将上一次节点的next(下次循环的节点地址)的地址赋给了二级指针】;
将新节点的地址(new指针变量存放的地址)给这个通过二级指针访问的一级指针(*cur = new)【后期看帮助理解:此时cur相当于head(两个二级指针),这个二级指针存放的地址是main中指向头结点的指针的地址 的复制品,但通过取它的值就可以访问带这个指向头节点的指针,以及后面的节点并更改该指针的方向(写这么多都在重复,也是为了重温时能有到多角度的引导,不懂要细看)】

pNode phead = &head; 	//main中的指针

void insertN(pNode *head,pNode new,int posit){	
        pNode *cur = head;			//指向的指针指向头节点
        while(*cur != NULL){		//指向节点的指针不为空就遍历
                if((*cur)->data == posit){		//当前节点为插入节点
                        new->next = *cur;		//当前节点的地址给新节点的next   	
                     	/*这里注意跟cur = &new区别*/
                        *cur = new;				//指向新节点的地址      
                        return ;
                }
                /*不是指定的位置*/
                cur = &((*cur)->next);	//指向下一个节点的地址给二级指针指针
        }
        return ;
}

带返回值实现

使用返回值进行插入相对于二级指针要易理解一些,通过返回值就可以将头节点的指针返回到主函数中头节点。因为是在指定节点的前面插入,所以定义一个pre指针用来保存上一个节点,使用当前指针pCurrt遍历链表。

pNode insertReVa(pNode p,pNode new,int position){
        pNode pCurrt = p;
        pNode pre = NULL;       //结构体指针用来存放当前节点的前一个节点
        while(pCurrt != NULL){
                if(pCurrt->data == position){
                        if(pre == NULL){                //前一个节点为空则为第一个节点
                                new->next = pCurrt;     //添加头节点
                                return new;
                        }else{
                                new->next = pre->next;  //插入节点
                                pre->next = new;
                                return p;
                        }
                }
                pre  = pCurrt;                  //前节点等于当前节点,当前节点后移
                pCurrt = pCurrt->next;
        }
        return p;
}

节点删除

二级指针实现

看懂了上面 节点增加->前插->二级指针法,这里就可以轻松理解了,方法是雷同的。不用添加新的节点,所以找到期望的位置就将指向当前节点的指针指向 当前节点的next的指向,这样就相当于上一个节点的next就跳过当前被删除的节点,直接指向下一个节点;
这里定义了一个结构体指针temp指向当前节点,链接了上一个节点与下一个节点后,对这个节点进行释放。
完成删除后,如果只用删除一个数,就可以直接返回;但如果需要删除所有相同的数就需要continue来跳过下一句的赋值:删掉节点后被指向的指针已经移到后一个节点,如果要删除的数在相邻的两个节点,就会出现漏删除,如果指定的数据在最后一个节点,就会造成非法访问。

void deletNode(pNode *head,int position){
        pNode *cur = head;
        while((*cur) != NULL){
                if((*cur)->data == position){
                        pNode temp = *cur;		//存放当前的节点
                        *cur = (*cur)->next;
                       	free(temp);				//释放被删除的当前节点
                        return;					//删除链表中第一个指定数据的节点
                        //continue;				//删除链表中所有这个数据的节点
                }
                cur = &((*cur)->next);
        }
        return;
}

*有一点注意,这里如果节点的定义不是通过malloc进行空间分配的而是普通变量,free()操作会导致其报错出现重复释放空间!

带返回值实现

这与插入的结构体指针返回法有一些不同,这里先对第一个节点进行了单独判断,非首个节点就对其下一个节点进行匹配,这样就不用定义一个结构体指针变量来记录前一个节点的地址

pNode deltNode(pNode head, int position){
        pNode p  = head;
        pNode tmp = head;		//记录要删除的节点为了将其释放
        if(p->data == position){		//相对第一个值进行判断
                p = p->next;	
                free(tmp);
                return p;
        }
        while(p->next != NULL){
                if(p->next->data == position){   	//对下一个节点的值进行判断
                        tmp = p->next;
                        p->next = p->next->next;
                        free(tmp);              //非malloc节点不可用
                        return head;
                }
                p = p->next;
        }
        puts("no such data!");
        return head;
}

链表的动态创建

静态创建链表十分麻烦,且需要大篇幅的重复的内容,所以动态创建成了创建链表的必经路,同时动态创建又分为从头插入和从尾插入

头插法

带返回值实现

新插入的节点放在最前面,对当前头节点进行判断,如果为空,当前新节点就为头节点;另外头插函数还可以单独调用

/*头插法-返回值法*/
//头插实现
pNode insertHead(pNode head,pNode new){
        if(head == NULL){       //无头节点则新节点为头
                head = new;
        }else{
                new->next = head;
                head = new;		//新节点为头
        }
        return head;
}
//创建节点
pNode creatLnkList(pNode head){
        while(1){
                pNode new = (pNode)malloc(sizeof(node));		
                puts("enter the data for this node:");
                scanf("%d",&new->data);		//初始化新节点
                new->next = NULL;
                if(new->data == 0){
                        return head;
                }
                head = insertHead(head,new);
        }
        return head;
}
二级指针实现

以下是用二级指针实现的,相对来说比在指定位置插入简单,创建节点代码几乎一样,只是注意传入的参数是指针的地址以实现更改指针指向的位置,头插法的实现基本类似返回值法。

//二级指针法
void insertHeadP(pNode *pCur,pNode new){
        if(*pCur == NULL){
                *pCur = new;		//新节点为头节点
        }else{
                new->next = *pCur;		//原头节点接在新节点后
                *pCur = new;
        }
        return ;
}
//创建节点
void creatLnkListP(pNode *head){
        pNode *cur = head;
        while(1){
                pNode new = (pNode)malloc(sizeof(node));
                puts("enter the data for this node:");
                scanf("%d",&new->data);		//初始化新节点
                new->next = NULL;
                if(new->data == 0){
                        return;
                }
                insertHeadP(cur,new);
        }
}

尾插法

尾插发分开实现是为了完整性,如下代码可以无返回值,且只用传递一级指针的情况下实现尾插。

void insertTail(pNode head,pNode new){
        pNode p = head;
        if(head == NULL){       //无头节点则新节点为头
                head->data = new->data;
                head->next = NULL;
                return;
        }
        while(p->next != NULL){
                p = p->next;
        }
        p->next = new;
        return ;
}

但是如果是从头创建链表则不可以使用这段代码,因为要将头节点指着指向新的节点,这就需要改动指针的值或者将新的头节点地址作为返回值传回来,两种方式实现如下:

带返回值实现

尾插区别在于要先对链表进行遍历,当判断到达最后一个节点是,将新节点地址给当前节点的next里即可

/*尾插法*/
//带返回值实现
pNode insertTail(pNode head,pNode new){
        pNode p = head;
        if(head == NULL){       //无头节点则新节点为头
                head = new;
                return head;
        }
        while(p->next != NULL){
                p = p->next;
        }
        p->next = new;
        return head;
}
二级指针实现

使用二级指针尾插其实和头插基本一模一样,因为二级指针需要指向头不变,所以定义变量指向二级指针中指针的指向,如果只是使用尾插插入元素,那可以直接使用 带参数返回值方法 那段代码,无需另写,本段代码只是为了

void insertTailP(pNode *pCur,pNode new){
        pNode cur = *pCur;              //定义结构体指针变量存放二级指针中指针指向的变量
        if(*pCur == NULL){
                *pCur = new;
                return ;
        }
        while(cur->next != NULL){
                cur = cur->next;
        }
        cur->next = new;
        return ;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
考试大纲 1 基本要求 1.熟悉Visual C++集成开发环境。 2.掌握结构化程序设计的方法,具有良好的程序设计风格。 3.掌握程序设计中简单的数据结构和算法并能阅读简单的程序。 4.在Visual C++集成环境下,能够编写简单的C 程序,并具有基本的纠错和调试程序的能力。 2 考试内容 一、C语言程序的结构 1.程序的构成,main函数和其他函数。 2.头文件,数据说明,函数的开始和结束标志以及程序中的注释。 3.源程序的书写格式。 4.C语言的风格。 二、数据类型及其运算 1.C的数据类型(基本类型,构造类型,指针类型,无值类型)及其定义方法。 2.C运算符的种类、运算优先级和结合性。 3.不同类型数据间的转换与运算。 4.C表达式类型(赋值表达式,算术表达式,关系表达式,逻辑表达式,条件表达式,逗号表达式)和求值规则。  三、基本语句 1.表达式语句,空语句,复合语句。 2.输入输出函数的调用,正确输入数据并正确设计输出格式。 四、选择结构程序设计 1.用if语句实现选择结构。 2.用switch语句实现多分支选择结构。 3.选择结构的嵌套。 五、循环结构程序设计 1.for循环结构。 2.while和do-while循环结构。 3.continue语句和break语句。 4.循环的嵌套。 六、数组的定义和引用 1.一维数组和二维数组的定义、初始化和数组元素的引用。 2.字符串与字符数组。 七、函数 1.库函数的正确调用。 2.函数的定义方法。 3.函数的类型和返回值。 4.形式参数与实际参数,参数值的传递。 5.函数的正确调用,嵌套调用,递归调用。 6.局部变量和全局变量。 7.变量的存储类别(自动,静态,寄存器,外部),变量的作用域和生存期。 八、编译预处理 1.宏定义和调用(不带参数的宏,带参数的宏)。 2.“文件包含”处理。 九、指针 1.地址与指针变量的概念,地址运算符与间址运算符。 2.一维、二维数组和字符串的地址以及指向变量、数组、字符串、函数、结构体的指针变量的 定义。通过指针引用以上各类型数据。 3.用指针作函数参数。 4.返回地址值的函数。 5.指针数组,指向指针的指针。 十、结构体(即“结构”)与共同体(即“联合”) 1.用typeof说明一个新类型。 2.结构体和共用体类型数据的定义和成员的引用。 3.通过结构体构成链表,单向链表的建立,结点数据的输出、删除与插入。 十一、位运算 1.位运算符的含义和使用。 2.简单的位运算。 十二、文件操作 只要求缓冲文件系统(即高级磁盘I/O系统),对非标准缓冲文件系统(即低级磁盘I/O系统)不要求。 1.文件类型指针(FILE类型指针)。 2.文件的打开与关闭(fopen,fclose)。 3.文件的读写(fputc,fgetc,fputs,fgets,fread,fwrite,fprintf,fscanf函数的应用),文件的定位(rewind,fseek函数的应用)。 3 考试方式 上机考试,考试时长120分钟,满分100分。 1.题型及分值 单项选择题40分(含公共基础知识部分10分)。 操作题60分(包括程序填空题、程序修改题及程序设计题)。 2.考试环境 操作系统:中文版Windows 7。 开发环境:Microsoft Visual C++ 2010学习版。
本书是关于计算机科学与工程领域的基础性研究科目之一——数据结构与算法的专著。 本书在简要回顾了基本的C++ 程序设计概念的基础上,全面系统地介绍了队列、堆栈、树、图等基本数据结构,以及贪婪算法、分而治之算法、分枝定界算法等多种算法设计方法,为数据结构与算法的继续学习和研究奠定了一个坚实的基础。更为可贵的是,本书不仅仅介绍了理论知识,还提供了50多个应用实例及600多道练习题。 本书内容广博权威,结构清晰合理,是一本全新的有关数据结构与算法的教材,对于计算机科学与工程领域的从业人员也是一本很好的参考书。 目 录 译者序 前言 第一部分 预备知识 第1章 C++程序设计 1 1.1 引言 1 1.2 函数与参数 2 1.2.1 传值参数 2 1.2.2 模板函数 3 1.2.3 引用参数 3 1.2.4 常量引用参数 4 1.2.5 返回值 4 1.2.6 递归函数 5 1.3 动态存储分配 9 1.3.1 操作符new 9 1.3.2 一维数组 9 1.3.3 异常处理 10 1.3.4 操作符delete 10 1.3.5 二维数组 10 1.4 类 13 1.4.1 类Currency 13 1.4.2 使用不同的描述方法 18 1.4.3 操作符重载 20 1.4.4 引发异常 22 1.4.5 友元和保护类成员 23 1.4.6 增加#ifndef, #define和#endif语句 24 1.5 测试与调试 24 1.5.1 什么是测试 24 1.5.2 设计测试数据 26 1.5.3 调试 28 1.6 参考及推荐读物 29 第2章 程序性能 30 2.1 引言 30 2.2 空间复杂性 31 2.2.1 空间复杂性的组成 31 2.2.2 举例 35 2.3 时间复杂性 37 2.3.1 时间复杂性的组成 37 2.3.2 操作计数 37 2.3.3 执行步数 44 2.4 渐进符号(O、 健?、 o) 55 2.4.1 大写O符号 56 2.4.2 椒?58 2.4.3 符号 59 2.4.4 小写o符号 60 2.4.5 特性 60 2.4.6 复杂性分析举例 61 2.5 实际复杂性 66 2.6 性能测量 68 2.6.1 选择实例的大小 69 2.6.2 设计测试数据 69 2.6.3 进行实验 69 2.7 参考及推荐读物 74 第二部分 数据结构 第3章 数据描述 75 3.1 引言 75 3.2 线性表 76 3.3 公式化描述 77 3.3.1 基本概念 77 3.3.2 异常类NoMem 79 3.3.3 操作 79 3.3.4 评价 83 3.4 链表描述 86 3.4.1 类ChainNode 和Chain 86 3.4.2 操作 88 3.4.3 扩充类Chain 91 3.4.4 链表遍历器类 92 3.4.5 循环链表 93 3.4.6 与公式化描述方法的比较 94 3.4.7 链表 95 3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子排序 111 3.8.2 基数排序 116 3.8.3 等价类 117 3.8.4 凸包 122 3.9 参考及推荐读物 127 第4章 数组和矩阵 128 4.1 数组 128 4.1.1 抽象数据类型 128 4.1.2 C++数组 129 4.1.3 行主映射和列主映射 129 4.1.4 类Array1D 131 4.1.5 类Array2D 133 4.2 矩阵 137 4.2.1 定义和操作 137 4.2.2 类Matrix 138 4.3 特殊矩阵 141 4.3.1 定义和应用 141 4.3.2 对角矩阵 143 4.3.3 三对角矩阵 144 4.3.4 三角矩阵 145 4.3.5 对称矩阵 146 4.4 稀疏矩阵 149 4.4.1 基本概念 149 4.4.2 数组描述 149 4.4.3 链表描述 154 第5章 堆栈 161 5.1 抽象数据类型 161 5.2 派生类和继承 162 5.3 公式化描述 163 5.3.1 Stack的效率 164 5.3.2 自定义Stack 164 5.4 链表描述 166 5.5 应用 169 5.5.1 括号匹配 169 5.5.2 汉诺塔 170 5.5.3 火车车厢重排 172 5.5.4 开关盒布线 176 5.5.5 离线等价类问题 178 5.5.6 迷宫老鼠 180 5.6 参考及推荐读物 188 第6章 队列 189 6.1 抽象数据类型 189 6.2 公式化描述 190 6.3 链表描述 194 6.4 应用 197 6.4.1 火车车厢重排 197 6.4.2 电路布线 201 6.4.3 识别图元 204 6.4.4 工厂仿真 206 6.5 参考及推荐读物 217 第7章 跳表和散列 218 7.1 字典 218 7.2 线性表描述 219 7.3 跳表描述 222 7.3.1 理想情况 222 7.3.2 插入和删除 223 7.3.3 级的分配 224 7.3.4 类SkipNode 224 7.3.5 类SkipList 225 7.3.6 复杂性 229 7.4 散列表描述 229 7.4.1 理想散列 229 7.4.2 线性开型寻址散列 230 7.4.3 链表散列 234 7.5 应用——文本压缩 238 7.5.1 LZW压缩 239 7.5.2 LZW压缩的实现 239 7.5.3 LZW解压缩 243 7.5.4 LZW解压缩的实现 243 7.6 参考及推荐读物 247 第8章 二叉树和其他树 248 8.1 树 248 8.2 二叉树 251 8.3 二叉树的特性 252 8.4 二叉树描述 253 8.4.1 公式化描述 253 8.4.2 链表描述 254 8.5 二叉树常用操作 256 8.6 二叉树遍历 256 8.7 抽象数据类型BinaryTree 259 8.8 类BinaryTree 260 8.9 抽象数据类型及类的扩充 263 8.9.1 输出 263 8.9.2 删除 264 8.9.3 计算高度 264 8.9.4 统计节点数 265 8.10 应用 265 8.10.1 设置信号放大器 265 8.10.2 在线等价类 268 8.11 参考及推荐读物 275 第9章 优先队列 276 9.1 引言 276 9.2 线性表 277 9.3 堆 278 9.3.1 定义 278 9.3.2 最大堆的插入 279 9.3.3 最大堆的删除 279 9.3.4 最大堆的初始化 280 9.3.5 类MaxHeap 281 9.4 左高树 285 9.4.1 高度与宽度优先的最大及最小 左高树 285 9.4.2 最大HBLT的插入 287 9.4.3 最大HBLT的删除 287 9.4.4 合并两棵最大HBLT 287 9.4.5 初始化最大HBLT 289 9.4.6 类MaxHBLT 289 9.5 应用 293 9.5.1 堆排序 293 9.5.2 机器调度 294 9.5.3 霍夫曼编码 297 9.6 参考及推荐读物 302 第10章 竞?303 10.1 引言 303 10.2 抽象数据类型WinnerTree 306 10.3 类WinnerTree 307 10.3.1 定义 307 10.3.2 类定义 307 10.3.3 构造函数、析构函数及Winner 函数 308 10.3.4 初始化赢者树 308 10.3.5 重新组织比赛 310 10.4 输者树 311 10.5 应用 312 10.5.1 用最先匹配法求解箱子装载 问题 312 10.5.2 用相邻匹配法求解箱子装载 问题 316 第11章 搜索树 319 11.1 二叉搜索树 320 11.1.1 基本概念 320 11.1.2 抽象数据类型BSTree和 IndexedBSTree 321 11.1.3 类BSTree 322 11.1.4 搜索 322 11.1.5 插入 323 11.1.6 删除 324 11.1.7 类DBSTree 326 11.1.8 二叉搜索树的高度 327 11.2 AVL树 328 11.2.1 基本概念 328 11.2.2 AVL树的高度 328 11.2.3 AVL树的描述 329 11.2.4 AVL搜索树的搜索 329 11.2.5 AVL搜索树的插入 329 11.2.6 AVL搜索树的删除 332 11.3 红-黑树 334 11.3.1 基本概念 334 11.3.2 红-黑树的描述 336 11.3.3 红-黑树的搜索 336 11.3.4 红-黑树的插入 336 11.3.5 红-黑树的删除 339 11.3.6 实现细节的考虑及复杂性分析 343 11.4 B-树 344 11.4.1 索引顺序访问方法 344 11.4.2 m 叉搜索树 345 11.4.3 m 序B-树 346 11.4.4 B-树的高度 347 11.4.5 B-树的搜索 348 11.4.6 B-树的插入 348 11.4.7 B-树的删除 350 11.4.8 节点结构 353 11.5 应用 354 11.5.1 直方图 354 11.5.2 用最优匹配法求解箱子装载 问题 357 11.5.3 交叉分布 359 11.6 参考及推荐读物 363 第12章 图 365 12.1 基本概念 365 12.2 应用 366 12.3 特性 368 12.4 抽象数据类型Graph和Digraph 370 12.5 无向图和有向图的描述 371 12.5.1 邻接矩阵 371 12.5.2 邻接压缩表 373 12.5.3 邻接链表 374 12.6 网络描述 375 12.7 类定义 376 12.7.1 不同的类 376 12.7.2 邻接矩阵类 377 12.7.3 扩充Chain类 380 12.7.4 类LinkedBase 381 12.7.5 链接类 382 12.8 图的遍历 386 12.8.1 基本概念 386 12.8.2 邻接矩阵的遍历函数 387 12.8.3 邻接链表的遍历函数 388 12.9 语言特性 389 12.9.1 虚函数和多态性 389 12.9.2 纯虚函数和抽象类 391 12.9.3 虚基类 391 12.9.4 抽象类和抽象数据类型 393 12.10 图的搜索算法 394 12.10.1 宽度优先搜索 394 12.10.2 类Network 395 12.10.3 BFS的实现 395 12.10.4 BFS的复杂性分析 396 12.10.5 深度优先搜索 397 12.11 应用 399 12.11.1 寻找路径 399 12.11.2 连通图及其构件 400 12.11.3 生成树 402 第三部分 算法设计方法 第13章 贪婪算法 405 13.1 最优化问题 405 13.2 算法思想 406 13.3 应用 409 13.3.1 货箱装船 409 13.3.2 0/1背包问题 410 13.3.3 拓扑排序 412 13.3.4 二分覆盖 415 13.3.5 单源最短路径 421 13.3.6 最小耗费生成树 424 13.4 参考及推荐读物 433 第14章 分而治之算法 434 14.1 算法思想 434 14.2 应用 440 14.2.1 残缺棋盘 440 14.2.2 归并排序 443 14.2.3 快速排序 447 14.2.4 选择 452 14.2.5 距离最近的点对 454 14.3 解递归方程 462 14.4 复杂性的下限 463 14.4.1 最小最大问题的下限 464 14.4.2 排序算法的下限 465 第15章 动态规划 467 15.1 算法思想 467 15.2 应用 469 15.2.1 0/1背包问题 469 15.2.2 图像压缩 471 15.2.3 矩阵乘法链 476 15.2.4 最短路径 480 15.2.5 网络的无交叉子集 483 15.2.6 元件折叠 486 15.3 参考及推荐读物 491 第16章 回溯 492 16.1 算法思想 492 16.2 应用 496 16.2.1 货箱装船 496 16.2.2 0/1背包问题 503 16.2.3 最大完备子图 506 16.2.4 旅行商问题 508 16.2.5 电路板排列 510 第17章 分枝定界 516 17.1 算法思想 516 17.2 应用 519 17.2.1 货箱装船 519 17.2.2 0/1背包问题 526 17.2.3 最大完备子图 528 17.2.4 旅行商问题 529 17.2.5 电路板排列 532
谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会主席、北京市人民代表。他是我国计算机普及和高校计算机基础教育开拓者之一,现任全国高等院校计算机基础教育研究会会长、教育部全国计算机应用技术证书考试委员会主任委员。 谭浩强教授创造了3个世界纪录:(1)20年来他(及和他人合作)共编著出版了130本计算机著作,此外主编了250多本计算机书籍,是出版科技著作数量最多的人。(2)他编著和主编的书发行量超过4500万册,是读者最多的科技作家。我国平均每30人、知识分子每1.5人就拥有1本谭浩强教授编著的书。(3)他和别人合作编著的《BASIC语言》发行了1200万册,创科技书籍发行量的世界纪录。此外,他编著的《C程序设计》发行了600万册。他曾在中央电视台主讲了BASIC,FORTRAN,COBOL,Pascal,QBASIC,C,Visual Basic七种计算机语言,观众超过300万人。 在我国学习计算机的人中很少有不知道谭浩强教授的。他善于用容易理解的方法和语言说明复杂的概念。许多人认为他开创了计算机书籍贴近大众的新风,为我国的计算机普及事业做出了重要的贡献。 谭浩强教授曾获全国高校教学成果国家级奖、国家科技进步奖,以及北京市政府授予的“有突出贡献专家”称号。《计算机世界》报组织的“世纪评选”把他评为我国“20世纪最有影响的IT人物”10个人之一(排在第2位)。他的功绩是把千百万群众带入计算机的大门。 1 C语言概述 1.1 C语言的发展过程 1.2 当代最优秀的程序设计语言 1.3 C语言版本 1.4 C语言的特点 1.5 面向对象的程序设计语言 1.6 C和C++ 1.7 简单的C程序介绍 1.8 输入和输出函数 1.9 C源程序的结构特点 1.10 书写程序时应遵循的规则 1.11 C语言的字符集 1.12 C语言词汇 1.13 Turbo C 2.0 集成开发环境的使用 1.13.1 Turbo C 2.0 简介和启动 1.13.2 Turbo C 2.0 集成开发环境 1.13.3 File菜单 1.13.4 Edit 菜单 1.13.5 Run 菜单 1.13.6 Compile 菜单 11.13.7 Project 菜单 1.13.8 Options菜单 1.13.9 Debug 菜单 1.13.10 Break/watch 菜单 1.13.11 Turbo C 2.0 的配置文件 2 程序的灵魂—算法 2.1 算法的概念 21 2.2 简单算法举例 21 2.3 算法的特性 24 2.4 怎样表示一个算法 24 2.4.1 用自然语言表示算法 24 2.4.2 用流程图表示算法 24 2.4.3 三种基本结构和改进的流程图 28 2.4.4 用N-S 流程图表示算法 29 2.4.5 用伪代码表示算法 30 2.4.6 用计算机语言表示算法 31 2.5 结构化程序设计方法 31 3 数据类型、运算符与表达式 3.1 C语言的数据类型 32 3.2 常量与变量 33 23.2.1 常量和符号常量 33 3.2.2 变量 33 3.3 整型数据 34 3.3.1 整型常量的表示方法 34 3.3.2 整型变量 35 3.4 实型数据 37 3.4.1 实型常量的表示方法 37 3.4.2 实型变量 38 3.4.3 实型常数的类型 39 3.5 字符型数据 39 3.5.1 字符常量 39 3.5.2 转义字符 39 3.5.3 字符变量 40 3.5.4 字符数据在内存中的存储形式及使用方法 41 3.5.5 字符串常量 41 3.5.6 符号常量 42 3.6 变量赋初值 42 3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值表达式 47 33.10 逗号运算符和逗号表达式 48 3.11 小结 49 3.11.1 C的数据类型 49 3.11.2 基本类型的分类及特点 49 3.11.3 常量后缀 49 3.11.4 常量类型 49 3.11.5 数据类型转换 49 3.11.6 运算符优先级和结合性 50 表达式 50 4 最简单的 C程序设计—顺序程序设计 4.1 C语句概述 51 4.2 赋值语句 53 4.3 数据输入输出的概念及在 C 语言中的实现 54 4.4 字符数据的输入输出 54 4.4.1 putchar 函数(字符输出函数) 54 4.4.2 getchar函数(键盘输入函数) 55 4.5 格式输入与输出 55 4.5.1 printf 函数(格式输出函数) 56 4.5.2 scanf函数(格式输入函数)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值