我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C语言怎么实现堆及堆的结构与接口

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C语言怎么实现堆及堆的结构与接口

本文小编为大家详细介绍“C语言怎么实现堆及堆的结构与接口”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言怎么实现堆及堆的结构与接口”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

    一、堆的结构及实现(重要)

    1.1 二叉树的顺序结构

    普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。在现实中我们通常把堆 (一种完全二叉树) 使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

    1.2 堆的概念及结构

    堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。堆总是满足下列性质:

    • 堆中某个结点的值总是不大于或不小于其父结点的值;

    • 堆总是一棵完全二叉树。

    堆是非线性数据结构,相当于一维数组,有两个直接后继。

    【大根堆和小根堆】:

    根结点最大的堆叫做大根堆,树中所有父亲都大于或等于孩子。

    根结点最小的堆叫做小根堆,树中所有父亲都小于或等于孩子。

    C语言怎么实现堆及堆的结构与接口

    【思考】这个大根堆和小根堆有什么特点呢?

    最值总在 0 号位,根据这个特点我们就可以做很多事情,比如TopK问题 (在一堆数据里面找到前 K 个最大 / 最小的数),生活中也有很多实例,比如点餐软件中有上千家店铺,我想选出该地区好评最多的十家川菜店,我们不用对所有数据排序,只需要取出前 K 个最大 / 最小数据。使用堆排序效率也更高。

    1.3 堆的实现

    1.3.1 堆的向下调整算法

    下面给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:该节点的左右子树必须是一个 (大 / 小) 堆,才能调整。

    int array[] = { 27,15,19,18,28,34,65,49,25,37 }; // 根节点的左右子树都是小堆

    C语言怎么实现堆及堆的结构与接口

    上面的数组,因为根节点的左右子树都是小堆,所以我们从根节点开始调整,将其调成小堆。

    向下调整算法思路(调成小堆):

    从根节点开始,不断往下调。

    选出根节点的左右孩子中「最小的孩子」,与「父亲」进行比较。

    • 如果父亲小于孩子,就不需处理了,整个树已经是小堆了。

    • 如果父亲大于孩子,就跟父亲交换位置,并将原来小的孩子的位置当成父亲继续向下进行调整,直到调整到叶子结点为止。

    向下调整算法过程演示(调成小堆,把大的节点往下调整):

    C语言怎么实现堆及堆的结构与接口

    向下调整算法代码:

    // 向下调整算法,建小堆,把大的节点往下调整// 前提是:左右子树都是小堆void AdjustDown(int* a, int size, int parent){// 指向左孩子,默认左孩子最小int child = parent * 2 + 1;while (child < size){// 1. 选出左右孩子最小的那个,先判断右孩子是否存在if (child + 1 < size && a[child] > a[child + 1]){child++; // 指向右孩子}// 2. 最小的孩子与父亲比较if (a[parent] > a[child]) // 如果父亲大于孩子{// 父亲与孩子交换位置Swap(&a[parent], &a[child]);// 更新父子下标,原先最小的孩子作为父亲,继续往下调parent = child;child = parent * 2 + 1;}else // 如果父亲小于孩子,说明已经为小堆了,停止调整{break;}}}
    1.3.2 向下调整算法的时间复杂度

    我们以满二叉树计算,最坏情况下,向下调整算法最多进行满二叉树的高度减1次比较,则说明向下调整算法最多调整满二叉树的高度减1次,n 个节点的满二叉树高度为 log2(n+1),估算后所以时间复杂度为 O(log2n)。

    1.3.3 堆的创建(向下调整)

    下面给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但不是一个堆,我们需要通过算法把它构建成一个堆。如果根节点左右子树不是一个 (大 / 小) 堆,我们应该怎么调整呢?

    我们倒着调整,从下到上,从「倒数第一个非叶子节点的子树」开始,依次遍历完所有非叶子节点,分别对每个子树进行「向下调整」成 (大 / 小) 堆,一直调整到「根节点」,就可以建成一个 (大 / 小) 堆。

    为什么要倒着调整呢?因为这样我们可以把「倒数第一个非叶子节点的子树」的左右子树看成是一个 (大 / 小) 堆,此时才能去使用向下调整算法。比如下图中的黄色填充的子树,3 的左子树 6 就可以看成是一个大堆。

    【实例】:将下面的数组建成一个大堆

    int a[] = { 1,5,3,8,7,6 };

    C语言怎么实现堆及堆的结构与接口

    建堆过程演示(以建大堆为例):从下到上,依次遍历完所有非叶子节点,分别对每个子树进行向下调整。

    依次对 每一步 中,方框内的树 进行 向下调整 为一个 大堆。

    C语言怎么实现堆及堆的结构与接口

    建堆代码:

    // 交换函数void Swap(int* a, int* b){int tmp = *a;*a = *b;*b = tmp;}// 向下调整算法,建大堆,把小的节点往下调// 前提是:左右子树都是大堆void AdjustDown(int* a, int size, int parent){// 指向左孩子,默认左孩子最大int child = parent * 2 + 1;while (child < size){// 1. 选出左右孩子最大的那个,先判断右孩子是否存在if (child + 1 < size && a[child] < a[child + 1]){child++; // 指向右孩子}// 2. 最大的孩子与父亲比较if (a[parent] < a[child]) // 如果父亲小于孩子{// 父亲与孩子交换位置Swap(&a[parent], &a[child]);// 更新父子下标,原先最大的孩子作为父亲,继续往下调parent = child;child = parent * 2 + 1;}else // 如果父亲大于孩子,说明已经为大堆了,停止调整{break;}}}void HeapSort(int* a, int size){    int parent = ((size - 1) - 1) / 2; // 最后一个叶子节点的父亲的下标for (int i = parent; i >= 0; i--)  // 从下到上,依次遍历完所有子树,分别对其进行调整{AdjustDown(a, size, i);}        // 下面是排升序:int end = size - 1; // 记录堆中最后一个元素的下标while (end > 0){Swap(&a[0], &a[end]);  // 将堆顶元素和堆中最后一个元素交换,把最大的数(堆顶)放到最后AdjustDown(a, end, 0); // 不看最后一个数,从根节点开始,对前面的数进行向下调整成大堆end--;}}
    1.3.4 堆排序

    排升序 --> 建大堆:

    【思考】排升序,建小堆可以吗?-- 可以是可以,但没啥意思。

    首先对 n 个数建小堆,选出最小的数,接着对剩下的 n-1 个数建小堆,选出第2小的数,不断重复上述过程&hellip;&hellip;。建 n 个数的堆时间复杂度是O(N),所以上述操作时间复杂度为O(N2),效率太低,尤其是当数据量大的时候,效率更低,同时堆的价值没有被体现出来,还不如用直接排序。

    【最佳方法】排升序,因为数字越来越大,需要找到最大的数字,得建大堆

    • 首先对 n 个数建大堆。

    • 将最大的数(堆顶)和最后一个数交换,把最大的数放到最后。

    • 前面 n-1 个数的堆结构没有被破坏(最后一个数不看做堆里面的),根节点的左右子树依旧是大堆,所以我们进行一次向下调整成大堆即可选出第2大的数,放到倒数第二个位置,然后重复上述步骤&hellip;&hellip;。

    【时间复杂度】:建堆时间复杂度为O(N),向下调整时间复杂度为O(log2N),这里我们最多进行N-2次向下调整,所以堆排序时间复杂度为O(N*log2N),效率是很高的。

    C语言怎么实现堆及堆的结构与接口

    排降序 --> 建小堆:

    【最佳方法】排降序,因为数字越来越小,需要找到最小的数字,得建小堆

    • 首先对 n 个数建小堆。

    • 将最小的数(堆顶)和最后一个数交换,把最小的数放到最后。

    • 前面 n-1 个数的堆结构没有被破坏(最后一个数不看做堆里面的),根节点的左右子树依旧是小堆,所以我们进行一次向下调整成小堆即可选出第2小的数,放到倒数第二个位置,然后重复上述步骤&hellip;&hellip;。

    • 【时间复杂度】:建堆时间复杂度为O(N),向下调整时间复杂度为O(log2N),这里我们最多进行N-2次向下调整,所以堆排序时间复杂度为O(N*log2N),效率是很高的。

    1.3.5 建堆的时间复杂度

    因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明,计算起来比较好算(时间复杂度本来看的就是近似值,多几个节点不影响最终结果):

    建堆要从倒数第一个非叶子节点开始调整,也即是从倒数第二层开始调,可得出时间复杂度公式:

    T ( n ) = &sum; ( 每 层 节 点 数 &lowast; ( 堆 的 高 度 &minus; 当 前 层 数 ) )

    C语言怎么实现堆及堆的结构与接口

    所以,建堆的时间复杂度为O(N)。

    【上面学了那么多,这里小小总结一下】

    • 堆的向下调整算法就是,在该节点左右子树都是一个小/大堆的前提下,将以该节点为根的树调整成一个小/大堆。

    • 堆的创建就是倒着调整,从下到上,从倒数第一个非叶子节点的子树开始,依次遍历完所有子树,分别对其进行向下调整。

    • 时间复杂度:堆的向下调整算法为O(log2N),堆的创建为O(N)。

    二、堆的相关接口实现(以大堆为例)

    首先新建一个工程( 博主使用的是 VS2019 )

    • Heap.h(堆的类型定义、接口函数声明、引用的头文件)

    • Heap.c(堆接口函数的实现)

    • Test.c(主函数、测试堆各个接口功能)

    Heap.h 头文件代码如下:

    #pragma once#include<stdio.h>   // printf, perror#include<stdbool.h> // bool#include<assert.h>  // assert#include<stdlib.h>  // malloc, free#include<string.h>  // memcpytypedef int HPDataType;typedef struct Heap{HPDataType* a; // 指向动态开辟的数组int size;      // 数组中有效元素个数int capacity;  // d容量}Heap;// 交换函数void Swap(HPDataType* a, HPDataType* b);// 向下调整函数(调成大堆,把小的往下调)void AdjustDown(HPDataType* a, int size, int parent);// 向上调整函数(调成大堆,把大的往上调)void AdjustUp(HPDataType* a, int child);// 初始化堆void HeapInit(Heap* php, HPDataType* arr, int n);// 销毁堆void HeapDestroy(Heap* php);// 插入元素(插入到堆的末尾),插入后并保持它依然是堆void HeapPush(Heap* php, int x);// 删除堆顶元素,删除后保持它依然是堆void HeapPop(Heap* php);// 获取堆顶元素,也即是最值HPDataType HeapTop(Heap* php);// 判断堆是否为空,为空返回true,不为空返回falsebool HeapEmpty(Heap* php);// 获取堆中有效元素个数int HeapSize(Heap* php);// 打印堆void HeapPrint(Heap* php);

    2.1 堆的初始化

    堆的初始化,首先需要实现一个向下调整算法:

    // 交换函数void Swap(HPDataType* a, HPDataType* b){HPDataType tmp;tmp = *a;*a = *b;*b = tmp;}// 向下调整算法(调成大堆,把小的往下调)void AdjustDown(HPDataType* a, int size, int parent){// 左孩子下标,初始默认左孩子最大int child = parent * 2 + 1;while (child < size){// 选出左右孩子最大的那个,先判断右孩子是否存在if (child + 1 < size && a[child] < a[child + 1]){child++; // 右孩子最大}// 最大的孩子与父亲比较if (a[parent] < a[child]) // 如果父亲小于孩子{// 父亲与孩子交换位置Swap(&a[parent], &a[child]);// 更新父子下标,原先最大的孩子作为父亲,继续往下调parent = child;child = parent * 2 + 1;}else // 如果父亲大于孩子,说明已经为大堆了,停止调整{break;}}}

    堆的初始化代码:

    // 初始化堆,用一个给定的数组来初始化void HeapInit(Heap* php, HPDataType* arr, int n){assert(php); // 断言// 动态开辟n个空间php->a = (HPDataType*)malloc(sizeof(HPDataType) * n);if (php->a == NULL){perror("malloc");exit(-1);}// 把给定数组的各元素值拷贝过去memcpy(php->a, arr, sizeof(HPDataType) * n);php->size = php->capacity = n;// 建堆(建大堆)int parent = ((php->size - 1) - 1) / 2; // 倒数第一个非叶子节点下标for (int i = parent; i >= 0; i--) // 从下到上,依次遍历完所有子树,分别对其进行调整{AdjustDown(php->a, php->size, i);}}

    2.2 堆的销毁

    // 销毁堆void HeapDestroy(Heap* php){assert(php);free(php->a); // 释放动态开辟的空间php->a = NULL;php->size = php->capacity = 0;}

    2.3 堆的插入

    先插入一个新元素到数组的尾上,从插入的新元素开始,进行向上调整算法,直到满足(大/小)堆。

    堆的插入过程演示:

    C语言怎么实现堆及堆的结构与接口

    堆的插入,首先需要实现一个向上调整算法:

    // 向上调整算法(调成大堆,把大的往上调)void AdjustUp(HPDataType* a, int child){// 父节点的下标int parent = (child - 1) / 2;//while (parent >= 0) parent不会小于0while (child > 0){// 孩子与父亲进行比较if (a[child] > a[parent]) // 如果孩子大于父亲{// 孩子与父亲交换Swap(&a[child], &a[parent]);// 更新父子下标,原先父亲作为孩子,继续往上调child = parent;parent = (child - 1) / 2;}else // 如果孩子小于父亲,说明已经为大堆了,停止调整{break;}}}

    堆的插入代码:

    // 插入元素(插入到堆的末尾),插入后并保持它依然是堆void HeapPush(Heap* php, int x){assert(php);// 先检查空间是否已满if (php->capacity == php->size){// 增容两倍php->capacity *= 2;HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * php->capacity);if (tmp != NULL){php->a = tmp;tmp = NULL;}}// 插入元素php->a[php->size] = x;php->size++;// 从插入的元素开始,进行向上调整,保持它依然是堆AdjustUp(php->a, php->size - 1);}

    2.4 堆的删除

    • 将堆顶元素和最后一个元素交换(这样就变成尾删了,很方便)

    • 删除堆中最后一个元素

    • 从根节点开始,对剩下元素进行向下调整,调成(大/小)堆

    堆的删除过程演示:

    C语言怎么实现堆及堆的结构与接口

    堆的插入,首先需要实现一个向下调整算法:前面已经实现过了,这里就不展示了。

    堆的删除代码:

    // 删除堆顶元素,删除后保持它依然是堆void HeapPop(Heap* php){assert(php);assert(!HeapEmpty(php)); // 堆不能为空// 将堆顶元素和最后一个元素交换Swap(&php->a[0], &php->a[php->size - 1]);// 删除堆中最后一个元素php->size--;// 从根节点开始,对剩下元素进行向下调整成大堆,保持它依然是堆AdjustDown(php->a, php->size, 0);}

    2.5 获取堆顶元素

    // 获取堆顶元素,也即是最值HPDataType HeapTop(Heap* php){assert(php);assert(!HeapEmpty(php)); // 堆不能为空return php->a[0];}

    2.6 堆的判空

    // 判断堆是否为空,为空返回true,不为空返回falsebool HeapEmpty(Heap* php){assert(php);return php->size == 0;}

    2.7 找出堆中前k个最大元素

    堆的相关接口实现好了,因为是大堆,所以我们可以很方便的来找出堆中前 k 个最大元素。

    这里要和前面的堆排序区分开哦,这里我们并不是在堆中对所有元素排好序。

    void TestHeap(){int a[] = { 1,5,3,8,7,6 };Heap hp;HeapInit(&hp, a, sizeof(a) / sizeof(a[0])); // 初始化堆int k = 0;scanf("%d", &k);printf("找出堆中前%d个最大元素:\n", k);while (!HeapEmpty(&hp) && k--){printf("%d ", HeapTop(&hp)); // 获取堆顶元素HeapPop(&hp); // 删除堆顶元素}printf("\n");}

    运行结果:

    C语言怎么实现堆及堆的结构与接口

    2.8 堆的创建(向上调整)

    下面给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但不是一个堆,我们需要通过「向上调整算法」把它构建成一个堆。如果根节点左右子树不是一个 (大 / 小) 堆,我们应该怎么调整呢?

    我们从上到下,从「第一个节点(也就是根节点)的左孩子」开始,依次遍历完所有节点,分别对每个节点进行「向上调整」,一直到「最后一个节点」,就可以建成一个 (大 / 小) 堆。

    我们把数组中的「第一个元素」看作是一个「堆」,剩余的元素依次插入到这个「堆」中。前面我们也实现了堆的插入接口,原理就是向上调整。

    C语言怎么实现堆及堆的结构与接口

    // 向上调整算法建堆void CreateHeap(int* a, int size){// 把第一个元素看作是堆,剩余的元素依次插入堆中for (int i = 1; i < size; i++){AdjustUp(a, i);}}

    读到这里,这篇“C语言怎么实现堆及堆的结构与接口”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    C语言怎么实现堆及堆的结构与接口

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    C语言怎么实现堆及堆的结构与接口

    本文小编为大家详细介绍“C语言怎么实现堆及堆的结构与接口”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言怎么实现堆及堆的结构与接口”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、堆的结构及实现(重要)1.
    2023-06-30

    C语言堆怎么实现和堆排序是什么

    这篇文章主要介绍了C语言堆怎么实现和堆排序是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言堆怎么实现和堆排序是什么文章都会有所收获,下面我们一起来看看吧。一、本章重点堆的介绍堆的接口实现堆排序二、堆2
    2023-06-29

    C语言数据结构堆的基本操作实现是怎样的

    本篇文章为大家展示了C语言数据结构堆的基本操作实现是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1.基本函数实现a.代码1(向下调整)void AdjustDown(DateType*a,
    2023-06-21

    C语言数据结构之队列怎么定义与实现

    今天小编给大家分享一下C语言数据结构之队列怎么定义与实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、队列的性质上次我们
    2023-07-02

    C语言数据结构之栈与队列怎么相互实现

    本篇内容介绍了“C语言数据结构之栈与队列怎么相互实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、用对列实现栈题干要求:细节分析:队列是
    2023-07-02

    C语言线索二叉树结构怎么实现

    这篇文章主要讲解了“C语言线索二叉树结构怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言线索二叉树结构怎么实现”吧!线索二叉树的意义对于一个有n个节点的二叉树,每个节点有指向左右
    2023-06-30

    C语言数据结构之单链表怎么实现

    本文小编为大家详细介绍“C语言数据结构之单链表怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言数据结构之单链表怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一.为什么使用链表在学习链表以前,
    2023-07-02

    C语言多维数组数据结构怎么实现

    这篇文章主要介绍“C语言多维数组数据结构怎么实现”,在日常操作中,相信很多人在C语言多维数组数据结构怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言多维数组数据结构怎么实现”的疑惑有所帮助!接下来
    2023-06-25

    怎么用C语言代码实现复数的加减及输出结构体

    这篇“怎么用C语言代码实现复数的加减及输出结构体”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么用C语言代码实现复数的加减
    2023-06-29

    GO语言怎么实现支持O(log(n))随机删除元素的堆

    今天小编给大家分享一下GO语言怎么实现支持O(log(n))随机删除元素的堆的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。背
    2023-07-06

    C语言顺序表的基本结构与实现思路详解

    顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。本文将通过示例为大家讲解一下顺序表的基本操作,需要的可以参考一下
    2023-02-13

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录