一、

1、线性表

  线性表包括顺序存储结构(用一段连续地址存储)和链式存储结构(数据域+指针域)。顺序存储结构的代表是C/C++中的数组,其读时间复杂度为O(1),插入/删除为O(n),因为从插入/删除位置到最后一个元素都要向前/后移动一个位置。链式存储结构包括单链表(普通链表)、循环链表、双向链表等,单链表的读取为O(n),插入/删除O(n)——不清楚第i个元素指针位置时,但是已知时为O(1),代表为list容器。

2、栈

  属于特殊的线性表,它一种先进后出的数据结构,代表为STL的stack。

3、队列

  属于特殊的线性表,它一种先进先出的数据结构,代表为queue。

4、树

  分为二叉树和多叉树(N叉树),map和set内部使用红黑树结构,在最坏的情况下查找、插入和删除仅消耗对数时间log(n)。

5、哈希表

  STL中的unorder_map和unorder_set使用的就是hash table结构,查找、插入和删除消耗为常数级别O(1)。

二、

1、静态数组

  静态数组就是大小固定不能扩展的数组,如C中普通数组、C++11中array。

2、动态数组

  动态数组的空间大小在需要的时候可以进行再分配,其代表为vector。由于数组的特点,在位置0插入需要将整个数组后移一个位置来腾出空间,删除位置0的元素则需要将剩余元素前移一个位置,这两种最坏的情况为O(n)。所以vector只适合在末尾添加或删除元素,使用[]或迭代器随机访问是快速的。

  deque可以可以看作是vector的增强版,它增加了在头部快速插入和删除元素。

3、链表

  链表由一系列不必在内存中相连的结点组成,每个结点包含了结点元素和到后继结点的链。链表避免了插入和删除的线性开销,但随机访问效率很低。使用链表结构的代表是list容器,而且list是基于双向链表实现的。下图是普通链表与双向链表的示意图:

数据结构与STL容器

   数据结构与STL容器

 4、栈

  栈的特点是后进先出,位于栈顶的元素是唯一可见的元素。栈可以使用链表来实现,通过在链表顶端插入元素来实现push,通过删除链表顶端元素来实现pop,top操作返回顶端元素。c++中栈数据结构的实现是容器适配器stack,stack其所关联的基础容器可以为vector、list、deque,默认为deque。

  数据结构与STL容器

5、队列

  队列的特点是先进先出,队列也可以使用链表来实现,enqueue(入队)是在链表的末端插入一个元素,dequeue(出队)是删除并返回链表开头的元素。c++中队列数据结构的实现是容器适配器queue,其所关联的基础容器可以为list或deque,默认为deque。

   数据结构与STL容器

6、链表的创建和操作

数据结构与STL容器
typedef struct node
{
    int iIndex;
    struct node* pNext;
}Node, *NodePtr;

//创建链表
NodePtr CreateList(unsigned iLen)
{
    NodePtr pHeadNode = NULL, pLastNode = NULL;
    for (unsigned i = 0; i < iLen; i++)
    {
        NodePtr pNode = new Node;
        pNode->iIndex = i;
        if (pLastNode)
            pLastNode->pNext = pNode;
        else
            pHeadNode = pNode;

        pLastNode = pNode;
    }
    pLastNode->pNext = NULL;

    return pHeadNode;
}

//输出链表
void PrintList(NodePtr pHeadNode)
{
    NodePtr pNode = pHeadNode;
    do
    {
        cout << pNode->iIndex << ", ";
        pNode = pNode->pNext;
    } while (pNode);

    cout << endl;
}

//链表排序:利用选择排序法思想
void SelectSortList(NodePtr pHeadNode)
{
    NodePtr pNode = pHeadNode;
    while (pNode->pNext)
    {
        NodePtr pNodeMin = pNode;
        NodePtr pNodeNext = pNode->pNext;
        while (pNodeNext)
        {
            if (pNodeNext->iIndex < pNodeMin->iIndex)
                pNodeMin = pNodeNext;

            pNodeNext = pNodeNext->pNext;
        }

        if (pNodeMin != pNode)
            swap(&pNode->iIndex, &pNodeMin->iIndex);

        pNode = pNode->pNext;
    }
}

//合并两个有序链表为一个
NodePtr UnionList(NodePtr pHeadNode1, NodePtr pHeadNode2)
{
    NodePtr pHeadNode = new Node;//新的链表添加一个头结点
    NodePtr pNode1 = pHeadNode1, pNode2 = pHeadNode2, pNode = pHeadNode;

    while (pNode1 && pNode2)
    {
        if (pNode1->iIndex <= pNode2->iIndex)
        {
            pNode->pNext = pNode1;
            pNode = pNode->pNext;
            pNode1 = pNode1->pNext;
        }
        else
        {
            pNode->pNext = pNode2;
            pNode = pNode->pNext;
            pNode2 = pNode2->pNext;
        }
    }

    pNode->pNext = pNode1 ? pNode1 : pNode2;//插入剩余段

    NodePtr pReturnNode = pHeadNode->pNext;
    delete pHeadNode;//删除新链表的头结点
    return pReturnNode;
}

//链表逆序:定义三个节点指针分别指向前三个节点,第二个节点的pNext重新指向第一个节点,三个节点指针再往后移动,如此往复
NodePtr TurnList(NodePtr pHeadNode)
{
    if (pHeadNode->pNext)
    {
        NodePtr pLastNode = pHeadNode;
        NodePtr pNode = pLastNode->pNext;
        NodePtr pNextNode = pNode->pNext;

        while (pNextNode)
        {
            pNode->pNext = pLastNode;

            pLastNode = pNode;
            pNode = pNextNode;
            pNextNode = pNextNode->pNext;
        }

        pNode->pNext = pLastNode;
        pHeadNode->pNext = NULL;

        return pNode;
    }
    else
        return pHeadNode;
}
View Code

相关文章: