数据结构与算法——数据结构知识归纳

C++中,内存分为5个区:堆、栈、自由存储区、全局/静态存储区和常量存储区。

  • 栈:是由编译器在需要时自动分配,不需要时自动清除的变量存储区。通常存放局部变量、函数参数等。
  • 堆:是由new分配的内存块,由程序员释放(编译器不管),一般一个new与一个delete对应,一个new[]与一个delete[]对应。如果程序员没有释放掉,资源将由操作系统在程序结束后自动回收。
  • 自由存储区:是由malloc等分配的内存块,和堆十分相似,用free来释放。
  • 全局/静态存储区:全局变量和静态变量被分配到同一块内存中(在C语言中,全局变量又分为初始化的和未初始化的,C++中没有这一区分)。
  • 常量存储区:这是一块特殊存储区,里边存放常量,不允许修改。

(注意:堆和自由存储区其实不过是同一块区域,new底层实现代码中调用了malloc,new可以看成是malloc智能化的高级版本)

一、 堆与栈

(1)堆与栈的区别

  1.  管理方式:堆中资源由程序员控制(容易产生memory leak), 栈资源由编译器自动管理,无需手工控制。
  2.  系统响应:对于堆,应知道系统有一个记录空闲内存地址的链表,当系统收到程序申请时,遍历该链表,寻找第一个空间大于申请空间的堆结点,删    除空闲结点链表中的该结点,并将该结点空间分配给程序(大多数系统会在这块内存空间首地址记录本次分配的大小,这样delete才能正确释放本内存  空间,另外系统会将多余的部分重新放入空闲链表中)。对于栈,只要栈的剩余空间大于所申请空间,系统为程序提供内存,否则报异常提示栈出。
  3.  空间大小: 堆是不连续的内存区域(因为系统是用链表来存储空闲内存地址,自然不是连续的),堆大小受限于计算机系统中有效的虚拟内存(32bit  系统理论上是4G),所以堆的空间比较灵活,比较大。栈是一块连续的内存区域,大小是操作系统预定好的,windows下栈大小是2M(也有是1M,在  编译时确定,VC中可设置)。
  4.  碎片问题:对于堆,频繁的new/delete会造成大量碎片,使程序效率降低。 对于栈,它是一个先进后出的队列,进出一一对应,不会产生碎片。
  5.  生长方向:堆向上,向高地址方向增长。栈向下,向低地址方向增长。
  6.  分配方式: 堆都是动态分配(没有静态分配的堆)。栈有静态分配和动态分配,静态分配由编译器完成(如局部变量分配),动态分配由alloca函数分配,但栈的动态分配的资源由编译器进行释放,无需程序员实现。
  7.  分配效率:堆由C/C++函数库提供,机制很复杂。所以堆的效率比栈低很多。栈是极其系统提供的数据结构,计算机在底层对栈提供支持,分配专门寄存器存放栈地址,栈操作有专门指令。

 (2)程序操作

  • 栈(stack):先进后出(FILO)
stack<int> stk;
stk.empty()     如果栈为空返回true,否则返回false;
stk.size()     返回栈内元素的大小;
stk.pop()      从栈顶弹出一个成员;
stk.push()     向栈内压入一个成员;
stk.top()      返回栈顶,但不删除成员;
  • 队列(queue):先进先出(FIFO)
queue<int> que;
que.empty()      如果队列为空返回true,否则返回false;
que.size()       返回队列内元素的大小;
que.pop()       从队列弹出一个成员;
que.push()       向队列压入一个成员;
que.front()      返回到队首,但不删除成员;
que.back()       返回到队尾,但不删除成员;

       树是一些节点的集合,节点之间用边链接,节点之间不能有环路。上层的节点称为父节点,下层节点称为子节点。最上层的节点称为根节点。

      二叉树是特殊的树。对于每个节点而言,与之直接相连的子节点不能超过两个(可以为0)。左边的子节点称为左子树,右边的子节点称为右子树。如下图就是一颗二叉树:

与树相关的一些概念:

  •  树叶(叶子节点):没有任何子节点的节点。
  • 深度:对于任意节点N,其深度指的是从根节点到N的唯一路径的长。根的深度为0。深度最深的叶子节点的深度为树的深度。可以理解为:树根是一个入口,离树根越远,就越深。如上图:A、B、C的深度为1,D、E的深度为2。
  • 高:  对于任意节点N,从N到一片树叶的最远路径的长为N的高度。(只可以从从上到下不能经过从下到上的节点。)树叶的高为0。树的高为根的高。如上图,根的高度为2。A的高度为1,其他节点高度为0。
#include <algorithm>
make_heap: 根据指定的迭代器区间以及一个可选的比较函数,来创建一个heap. O(N)
push_heap: 把指定区间的最后一个元素插入到heap中. O(logN)
pop_heap: 弹出heap顶元素, 将其放置于区间末尾. O(logN)
sort_heap:堆排序算法,通常通过反复调用pop_heap来实现. N*O(logN)针。

c++11
is_heap: 判断给定区间是否是一个heap. O(N)
is_heap_until: 找出区间中第一个不满足heap条件的位置. O(N)

二、 链表

      链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。根据节点包含内容不同可以分为单向链表和双向链表。

单向链表的节点:

  1. 数据域:用于存储数据元素的值。
  2. 指针域(链域):用于存储下一个结点地址或者说指向其直接后继结点的指针。 
 struct Node{
     int value;
     Node * next;
 };

双向链表的节点:

  1. 数据域:用于存储数据元素的值。
  2. 左指针域(左链域):用于存储上一个结点地址或者说指向其直接前继结点的指针。
  3. 右指针域(右链域):用于存储下一个结点地址或者说指向其直接后继结点的指针。
 struct DNode{
     int value;
     DNode * left;
     DNode * right;
 };

数据域:用于存储数据元素的值。
指针域(链域):用于存储下一个结点地址或者说指向其直接后继结点的指针。常用操作:

//插入节点(单向链表)
//p节点后插入值为i的节点
void insertNode(Node *p, int i){
    Node* node = new Node;
    node->value = i;
    node->next = p->next;
    p->next = node;
}

//删除节点(单向链表)
void deleteNode(Node *p){
    p->value = p->next->value;
    p->next = p->next->next;
}
  • 使用stl的List库实现链表
//创建链表
list<int> lst1;                          //创建空list
list<int> lst2(5);                       //创建含有5个元素的list
list<int> lst3(lst2);                    //使用lst2初始化
list<int> lst4(lst2.begin(),lst2.end()); //使用lst2初始化

//基本操作
lst1.assign() 给list赋值 
lst1.back() 返回最后一个元素 
lst1.begin() 返回指向第一个元素的迭代器 
lst1.clear() 删除所有元素 
lst1.empty() 如果list是空的则返回true 
lst1.end() 返回末尾的迭代器 
lst1.erase() 删除一个元素 
lst1.front() 返回第一个元素 
lst1.get_allocator() 返回list的配置器 
lst1.insert() 插入一个元素到list中 
lst1.max_size() 返回list能容纳的最大元素数量 
lst1.merge() 合并两个list 
lst1.pop_back() 删除最后一个元素 
lst1.pop_front() 删除第一个元素 
lst1.push_back() 在list的末尾添加一个元素 
lst1.push_front() 在list的头部添加一个元素 
lst1.rbegin() 返回指向第一个元素的逆向迭代器 
lst1.remove() 从list删除元素 
lst1.remove_if() 按指定条件删除元素 
lst1.rend() 指向list末尾的逆向迭代器 
lst1.resize() 改变list的大小 
lst1.reverse() 把list的元素倒转 
lst1.size() 返回list中的元素个数 
lst1.sort() 给list排序 
lst1.splice() 合并两个list 
lst1.swap() 交换两个list 
lst1.unique() 删除list中重复的元素

参考

https://blog.csdn.net/u013846293/article/details/79410293?utm_source=blogxgwz1

堆和栈参考:https://blog.csdn.net/yangyong0717/article/details/78001609

链表参考:https://www.cnblogs.com/byonecry/p/4458821.html

二叉树参考:https://blog.csdn.net/u014182411/article/details/69831492/

                     https://blog.csdn.net/flyyufenfei/article/details/78175511

发布了53 篇原创文章 · 获赞 186 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/Kalenee/article/details/83180311