[Learning]数据结构笔记

  "程序员面试宝典中数据结构部分的笔记"

Posted by Stephen.Ri on March 2, 2018

链表

单链表

  1. 单链表的建立/测长/打印

  2. 单链表的删除:找上一个节点指针

  3. 单链表的插入:找上一个节点指针

  4. 单链表的排序:冒泡/选择/快排

  5. 单链表的逆置:三指针四步法:pPrev指向上一个节点,pCurr指向当前节点,pNext保存下一个节点。

pNext = pCurr->next;
pCurr-> = pPrev;
pPrev = pCurr;
pCurr = pNext;

双链表

与单链表区别不大。多了一个指向前一节点的指针ListNode * pre

循环链表

链表的尾元素的next指针指向队首元素。

队列 vs. 栈

队列:先进先出

:后进先出

用两个栈实现一个队列的功能

我们有两个栈stack1和stack2。
插入的时候都是直接用stack1.push(element)。
删除的时候:当stack2中不为空时,stack2中栈顶的元素就是最先进入队列的元素,可以弹出。如果stack2为空,我们就把stack1中的元素逐个弹出并压入stack2,因为先进入stack1的元素在栈底,经过弹出并压入之后处于stack2的栈顶,可以直接弹出。

树,图,哈希表

二叉树

前序遍历:根左右

中序遍历:左根右

后序遍历:左右根

二叉搜索树

对于树中的每个节点,它的左子树的所有节点的值都小于该节点值,它的右子树的所有节点的值都大于该节点的值。

每次插入的新节点都是新的叶子节点。

搜索,插入,删除的复杂度等于树高,O(log(n))

平衡二叉树

它的左右两棵子树的高度差的绝对值不超过1.

Trie树

又称单词查找树字典树,是一种哈希树的变种,是一种用于快速检索的多叉树结构。

典型应用是用于统计和排序大量的字符串,所以经常被搜索引擎系统用于文本词频统计。

排序算法

排序算法 最好情况 最差情况 平均情况 辅助空间 稳定性 类别
插入排序 O(n) O(n^2) O(n^2) O(1) 稳定 插入类
希尔排序 O(n^1.3) O(n^2) O(nlog(n)) O(1) 不稳定 插入类
选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 选择类
堆排序 O(nlog(n)) O(nlog(n)) O(nlog(n)) O(1) 不稳定 选择类
冒泡排序 O(n) O(n^2) O(n^2) O(1) 稳定 交换类
快速排序 O(nlog(n)) O(n^2) O(nlog(n)) O(logn) ~ O(n) 不稳定 交换类
归并排序 O(nlog(n)) O(nlog(n)) O(nlog(n)) O(1) 稳定 归并类

字符串

#include <cstring>

整数和字符串转化

  1. itoa:加’0’,再逆序

  2. atoi:减’0’,再乘10

都要考虑正负号

字符数组和strcpy

char * strcpy(char * strDest, const char * strSrc)
{
    assert(strSrc != NULL);
    char * address = strDest;
    while(*strSrc != '\0')
        *strDest++ = *strSrc++;
    return address;
}

数组初始化和数组越界

字符数组的初始化要求最后一个字符必须是’\0’

C++ String类

class String  
{  
public:  
    String(const char *str = NULL);// 普通构造函数    
    String(const String &other);// 拷贝构造函数    
    ~String(void);// 析构函数    
    String & operator = (const String &other);// 赋值函数    
private:  
    char *m_data;// 用于保存字符串    
};

下面是上面四个函数的具体实现

//  普通构造函数    
String::String(const char *str)  
{  
    if (str == NULL)  
    {  
        m_data = new char[1];// 得分点:对空字符串自动申请存放结束标志'\0'的,加分点:对m_data加NULL判断    
        *m_data = '\0';  
    }  
    else  
    {  
        int length = strlen(str);  
        m_data = new char[length + 1];// 若能加 NULL 判断则更好    
        strcpy(m_data, str);  
    }  
}  
  
  
// String的析构函数    
String::~String(void)  
{  
    delete[] m_data; // 或delete m_data;    
}  
  
  
//  拷贝构造函数    
String::String(const String &other)// 得分点:输入参数为const型    
{          
    int length = strlen(other.m_data);  
    m_data = new char[length + 1];//加分点:对m_data加NULL判断    
    strcpy(m_data, other.m_data);  
}  
  
//  重载+  
String String::operator+(const String &str) const  //重载+
{
    String newString;
    newString.length = length + str.size();
    newString.data = new char[newString.length + 1];
    strcpy(newString.data, data);
    strcat(newString.data, str.data);
    return newString;
}
  
//  赋值函数    
String & String::operator = (const String &other) // 得分点:输入参数为const型    
{  
    if (this == &other)//得分点:检查自赋值    
        return *this;   
    if (m_data)  
        delete[] m_data;//得分点:释放原有的内存资源    
    int length = strlen(other.m_data);  
    m_data = new char[length + 1];//加分点:对m_data加NULL判断    
    strcpy(m_data, other.m_data);  
    return *this;//得分点:返回本对象的引用      
}