数据结构——线性结构

来源:互联网 发布:域名是知识产权吗 编辑:程序博客网 时间:2024/05/21 01:42

线性结构区别于非线性结构,通常这种数据结构中的数据元素呈现一种线性关系。
主要包括数组、链表、栈和队列这四种。

数组

数组是一组有序定长的元素集合。
int array[] = {0,1,2,3,4,5,6};
由于数组的元素在内存中的地址是连续的,因此它的特点是随机访问速度快

多维数组

多维数组可以多下标表示类似平面甚至空间这种概念,其本质也是一维数组来实现。
int array[2][3] = {1,2,3,4,5,6};

动态数组

数组长度通常是固定的,在元素个数未知或需要改变的时候,我们需要动态数组,即容量可以动态增长的数组。
C++中的STL提供了一种容器vector可以实现非定长的数组。

#include <vector>using namespace std;vector<int> vec;

声明了vector容器变量vec后,可以进行以下操作:
1、通过push_back()pop_back()分别向容器中添加元素和删除元素;
2、通过empty()判断容器是否为空;
3、通过size()获取当前容器中实际元素个数;
4、通过capacity()获取为当前容器分配的大小;
5、通过max_size()返回容器可以容纳的最大元素个数;

看下面一段代码,判断容器是否为空,以及依次插入数据看max_size、size和capacity。

    if(vec.empty())        cout<<"vec is empty"<<endl;    cout<<vec.max_size()<<" "<<vec.size()<<" "<<vec.capacity()<<endl;    vec.push_back(1);    cout<<vec.max_size()<<" "<<vec.size()<<" "<<vec.capacity()<<endl;    vec.push_back(2);    cout<<vec.max_size()<<" "<<vec.size()<<" "<<vec.capacity()<<endl;    vec.push_back(3);    cout<<vec.max_size()<<" "<<vec.size()<<" "<<vec.capacity()<<endl;    vec.push_back(4);    cout<<vec.max_size()<<" "<<vec.size()<<" "<<vec.capacity()<<endl;    vec.push_back(5);    cout<<vec.max_size()<<" "<<vec.size()<<" "<<vec.capacity()<<endl;    vec.push_back(6);    cout<<vec.max_size()<<" "<<vec.size()<<" "<<vec.capacity()<<endl;

输出结果为:

vec is empty1073741823 0 01073741823 1 11073741823 2 21073741823 3 41073741823 4 41073741823 5 81073741823 6 8

可见,容器是有一个固定的最大值max_size,为1073741823,只要不超过这个值,你可以随意添加元素。
size为当前容器元素个数,capacity为容器可容纳元素个数,不小于size。
其实,容器内部有一套内存分配的规律,当分配的内存不够而此时又有新元素插入,会发生重新分配(包括新内存的分配,原始内存的回收,对象拷贝析构等等)。(重新分配通常将当前容量翻倍)
考虑容器重新分配过程中性能下降问题,如果有大量插入操作,最好提前设定容量大小,避免多次扩容操作带来的效率低下。

6、通过reserve()改变当前容器所分配空间的大小,为其申请特定容量;

如我们要循环插入数据时,使用reserve可以避免重新分配。

vec.reserve(1000);

7、通过resize(n)强制修改容器元素个数;
若n小于size,尾部元素会被销毁;若n大于size,则填充默认元素;若n大于capacity,则加入元素前重新分配。

举一个例子:

    for(int i = 0; i < 5; i++)        vec.push_back(i);    cout<<"size = "<<vec.size()<<" capacity = "<<vec.capacity()<<endl;    vec.resize(n);    cout<<"size = "<<vec.size()<<" capacity = "<<vec.capacity()<<endl;    vec.push_back(6);    cout<<"size = "<<vec.size()<<" capacity = "<<vec.capacity()<<endl;

输出结果为:

// n = 3时size = 5 capacity = 8size = 3 capacity = 8size = 4 capacity = 8// n = 7时size = 5 capacity = 8size = 7 capacity = 8size = 8 capacity = 8// n = 10时size = 5 capacity = 8size = 10 capacity = 10size = 11 capacity = 20

8、通过at(n)访问下标为n的元素,同数组的下标访问;

    for(int i = 0; i < vec.size(); i++)        cout<<vec.at(i)<<" ";

这句话是依次输出容器的所有元素,同vec[i]。

9、通过begin()end()返回容器起止元素的迭代器;
其中,begin()返回当前容器中起始位置的迭代器,end()返回当前容器中末尾位置的迭代器。
上面的依次输出可以写成这个样子:

    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;

10、通过front()back()返回容器起止元素的引用;
区别于上面的begin()和end(),是指向元素的指针;front()和back()返回元素的引用,因此可以直接访问元素。
注意:通过迭代器访问最后一个元素,需将end()迭代器减一。
如输出首位元素:

    vector<int>::iterator begin = vec.begin();    vector<int>::iterator end = vec.end();    cout<<*begin<<" "<<*(end-1)<<endl;    int front = vec.front();    int back = vec.back();    cout<<front<<" "<<back<<endl;

结果是一样的:

0 60 6

11、通过assign()向容器集体赋值;
assign(beg,end)会将[beg,end)前开后闭区间中的数据赋值给容器,assign(n,elem)则将n个elem的拷贝赋值给容器。
注意:元素会进行覆盖。
举例说明,直接赋值,assign拷贝和assign赋值:

    vec = {1, 2, 3, 4, 5, 6};    vecvec = {10, 20, 30};    vec = vecvec;    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;    vec.assign(vecvec.begin(), vecvec.end());    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;    vec.assign(10, 0);    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;

三次输出分别是:

10 20 3010 20 300 0 0 0 0 0 0 0 0 0

12、通过insert()进行元素插入,通过erase()进行元素删除;
两者都是通过迭代器操作的,insert会向迭代器所指的位置插入数据,原始数据后移;erase会删除迭代器指向的数据,后面的数据前移。
看一个插入的例子:

    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;    //在指定位置插入值为3的元素     vec.insert(vec.begin()+1, 3);    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;    //在指定位置插入4个值为2的元素     vec.insert(vec.begin()+5, 4, 2);    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;    //在指定位置插入区间[begin, end)的所有元素    vec.insert(vec.begin()+10, vecvec.begin(),vecvec.end());    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;

输出结果为:

1 1 1 1 1 1 1 1 1 11 3 1 1 1 1 1 1 1 1 11 3 1 1 1 2 2 2 2 1 1 1 1 1 11 3 1 1 1 2 2 2 2 1 10 20 30 1 1 1 1 1

再看一个删除的例子:

    //删除某个位置的元素    vec.erase(vec.begin());    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;    //删除指定位置区间[begin, end)的所有元素    vec.erase(vec.begin()+5, vec.begin()+8);    for(vector<int>::iterator i = vec.begin(); i != vec.end(); i++)        cout<<*i<<" ";    cout<<endl;

输出结果为:

3 1 1 1 2 2 2 2 1 10 20 30 1 1 1 1 13 1 1 1 2 1 10 20 30 1 1 1 1 1

13、 通过clear()清空当前容器;

    vec.clear();    if(vec.empty())        cout<<"vec is empty"<<endl;

输出为:

vec is empty

14、通过swap()实现交换数据;
如交换两个元素:

    vector<int> v1 = {1,2,3,4,5,6};    swap(v1[1], v1[3]);    for(vector<int>::iterator it = v1.begin(); it != v1.end(); it++)        cout<<*it<<" ";    cout<<endl;

交换后结果对比为:

1 4 3 2 5 6

交换两个容器:

    vector<int> v1 = {1,2,3,4,5,6};    vector<int> v2 = {10,20,30,40};    swap(v1, v2);    cout<<"v1 = ";    for(vector<int>::iterator it = v1.begin(); it != v1.end(); it++)        cout<<*it<<" ";    cout<<endl;    cout<<"v2 = ";    for(vector<int>::iterator it = v2.begin(); it != v2.end(); it++)        cout<<*it<<" ";    cout<<endl;

结果为:

v1 = 10 20 30 40v2 = 1 2 3 4 5 6

swap还可以用来调整内存。当为容器分配的内存过大而出现剩余时,通过vector<int>(vec).swap(vec);将容器的最大容量减少到目前所需的容量。
这条语句首先会建立一个临时容器,它是原始容器vec的一份拷贝,通过容器的拷贝构造函数来实现,因此只分配拷贝的元素所需要的内存,然后使用swap交换两个容器,最后销毁临时容器,实现将原始容器收缩到合适容量。

    cout<<"size = "<<vec.size()<<" capacity = "<<vec.capacity()<<endl;    vector<int>(vec).swap(vec);    cout<<"size = "<<vec.size()<<" capacity = "<<vec.capacity()<<endl;

收缩后的capacity等于size的值。

size = 5 capacity = 8size = 5 capacity = 5

15、通过rbegin()rend()获取反转后的容器的起止位置指针。
也即vec.begin() = vec.rend()-1vec.end() = vec.rbegin()-1,见下面的例子:

    vector<int> vec = {1,2,3,4,5,6};    cout<<*vec .begin()<<" "<<*(vec .end()-1)<<endl;    cout<<*vec .rbegin()<<" "<<*(vec .rend()-1)<<endl;

输出结果为:

1 66 1

16、最后加一点,用vector实现多维数组。其实就是相当于容器中的元素不再为简单的变量,而是数组或者容器。
看一个例子:

    vector<vector<int>> matrix;    vector<int> row1 = {1,2,3,4,5};    vector<int> row2 = {2,3,4,5,6};    vector<int> row3 = {3,4,5,6,7};    matrix.push_back(row1);    matrix.push_back(row2);    matrix.push_back(row3);    cout<<"matrix = "<<endl;    for(int i = 0; i < 3; i++)    {        for(int j = 0; j < 5; j++)            cout<<matrix[i][j]<<" ";        cout<<endl;    }

输出结果为一个二维数组:

matrix =1 2 3 4 52 3 4 5 63 4 5 6 7

注意:通过数组来实现线性表在内存中是连续存储的,因此可以通过通过下标来实现快速访问或者修改元素,高效便捷,但是插入和删除元素的开销太大。

为了提高在任意位置添加或者删除元素的效率,可以采用链式结构来实现线性表。

链表

链表区别于数组,它是一种物理存储非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接顺序实现的。
链表由一系列节点组成,每个节点包括数据部分和链部分,链指向另外的节点来实现逻辑顺序。当增删链表元素时,只需要修改链部分的指向,可以达到很高的效率。
根据链部分,可以将链表分为单向链表(单链表)和双向链表(双链表)。

  • 单链表:每个节点包含指向下一个节点的指针,为单向的;
  • 双链表:每个节点包含指向前一个节点和下一个节点的指针,为双向的;
  • 循环链表:链表的最后一个节点指向第一个节点,为一个环;

首先看一个链表元素的数据结构,以int类型为例。

struct Node{    int data;    Node *pre;    Node *next;};

这是一个有三个元素组成的结构体,为链表中的一个节点。data为数据域,也可以为其他类型甚至更复杂的数据结构;pre为指向上一个节点的指针,next为指向下一个节点的指针。

然后我们创建一个NodeList的类,里面实现了利用上面Node数据结构创建链表以及对这个链表增删等各种方法。这个类有两个私有成员,分别为一个int类型的count,表示链表的节点个数,一个指向Node类型的指针head,为这个链表的头节点。

class NodeList{    public:        NodeList();        ~NodeList();        int getSize();        Node* getNode(int i);        bool insertNode(int i, int data);        bool deleteNode(int i);        void print();    protected:    private:        int count;        Node *head;};

1.创建链表和删除链表

首先看下这个类的构造函数和析构函数。

    //ctor    cout<<"this is a constructor of NodeList"<<endl;    head = new Node();    head->pre = head->next = NULL;    count = 0;    //dtor    cout<<"this is a constructor of NodeList"<<endl;    while(head->next)    {        Node *tmp = head->next;        head->next = tmp->next;        delete tmp;        tmp = NULL;        count--;    }    delete head;    head = NULL;

构造函数很简单,就是初始化head节点(注意这里的head节点不存放数据,只是作为一个链表头存在),它的pre和next在初始化时都为空;
析构函数在最后退出时调用,需要释放链表的所有节点,我们首先会删除head后面的节点,最后删除head节点。

2.增加节点

增加节点需要输入两个参数,插入的位置和插入的数据内容。

    Node *tmp = head;    if(i < 0 || i > count)    {        cout<<"out of range"<<endl;        return false;    }    while(i != 0)    {        tmp = tmp->next;        i--;    }    Node *node = new Node();    node->data = data;    node->next = tmp->next;    node->pre = tmp;    tmp->next = node;    if(node->next)        node->next->pre = node;    count++;    return true;

首先判断插入范围,然后找到对应的位置(从0开始),然后将节点插入到两个节点之间,注意这里修改原始链表指针的顺序。
比如,我们要插入到tmp后面。
链表原始的结构是:··· ··· -> tmp -> tmp1 -> ··· ···
插入后的结构变成:··· ··· -> tmp -> node -> tmp1 -> ··· ···

3.删除节点

删除节点只需要输入删除的位置即可。

    Node *tmp = head;    if(i < 0 || i > count)    {        cout<<"out of range"<<endl;        return false;    }    while(i != 0)    {        tmp = tmp->next;        i--;    }    Node *node = tmp->next;    tmp->next = node->next;    tmp->next->pre = tmp;    delete node;    node = NULL;    count--;    return true;

跟插入一样,先判断插入范围,然后找到要删除的节点,整个过程跟插入是互逆的。

4.查找节点

查找节点允许我们根据位置查找相应的节点,这个查找过程的复杂度是O(n),因为需要遍历整个链表。

    Node *node = head->next;    if(i < 0 || i > count)    {        cout<<"out of range"<<endl;        return NULL;    }    while(i != 0)    {        node = node->next;        i--;    }    return node;

5.获取链表节点数

这个很简单,就是返回一个成员变量。

    return count;

6.输出链表

依次打印出链表的内容。

    Node *tmp = head->next;    cout<<"NodeList : ";    while(tmp)    {        cout<<tmp->data<<" ";        tmp = tmp->next;    }    cout<<endl;

看几个测试例子。

    NodeList nodelist;    cout<<"size = "<<nodelist.getSize()<<endl;    nodelist.insertNode(0, 0);    nodelist.insertNode(1, 1);    nodelist.insertNode(2, 2);    nodelist.insertNode(3, 3);    nodelist.insertNode(4, 4);    cout<<"size = "<<nodelist.getSize()<<endl;    nodelist.print();

输出为:

this is a constructor of NodeListsize = 0size = 5NodeList : 0 1 2 3 4this is a constructor of NodeList

查找某个位置的节点:

    cout<<"i = 0 : "<<nodelist.getNode(0)->data<<endl;    cout<<"i = 3 : "<<nodelist.getNode(3)->data<<endl;    cout<<"i = 6 : "<<nodelist.getNode(6)<<endl;

输出:

i = 0 : 0i = 3 : 3out of rangei = 6 : 0

删除操作:

    nodelist.deleteNode(0);    nodelist.print();    nodelist.insertNode(3, 5);    nodelist.print();    nodelist.deleteNode(2);    nodelist.print();

输出:

NodeList : 1 2 3 4NodeList : 1 2 3 5 4NodeList : 1 2 5 4

将该链表看作单链表进行逆序:

    NodeList reverse;    for(int i = 0; i < nodelist.getSize(); i++)    {        reverse.insertNode(0, nodelist.getNode(i)->data);    }    reverse.print();

输出:

NodeList : 4 3 2 1 0

除了数组和链表,还有两种特殊的线性表,分别为栈和队列。

栈(stack)是一端封闭的的线性表,对于元素的插入、删除、访问都只能在栈顶进行。因此栈的特点是LIFO(Last In First Out),即后进先出

栈的操作主要包括三种:

  • push:压栈,向栈中添加元素;
  • pop:出栈,返回并删除栈顶元素;
  • peek:返回栈顶元素。

这里给出栈的三种实现方式。

1.数组实现栈

定义一个Stack的类,成员变量为int类型的容器m_stack,存放栈元素,int类型的变量count,为栈元素个数。然后我们需要去实现push、pop、peek等操作栈的方法。

class Stack{    public:        Stack();        ~Stack();        void push(int data);        int pop();        int peek();        int getSize();        void print();    protected:    private:        vector<int> m_stack;        int count;};

实现起来比较简单,分别看下。

1.1 创建和销毁

没什么内容,就是为count赋个初值。

Stack::Stack(){    //ctor    cout<<"this is a ctor of stack"<<endl;    count = 0;}Stack::~Stack(){    //dtor    cout<<"this is a dtor of stack"<<endl;}

1.2 入栈

直接用vector的push_back函数,然后count加一。

void Stack::push(int data){    m_stack.push_back(data);    count++;}

1.3 出栈

保留栈顶元素,调用vector的pop_back函数,然后count减一。

int Stack::pop(){    count--;    int res = m_stack.at(count);    m_stack.pop_back();    return res;}

1.4 取栈顶元素

直接返回最后一个元素。

int Stack::peek(){    return m_stack.at(count-1);}

1.5 获取栈大小

直接返回count。

int Stack::getSize(){    return m_stack.size();}

1.6 打印栈

遍历数组即可。

void Stack::print(){    cout<<"m_stack : ";    for(vector<int>::iterator i = m_stack.begin(); i != m_stack.end(); i++)    {        cout<<*i<<" ";    }    cout<<endl;}

看一下测试代码:

    Stack stack;    stack.push(0);    stack.push(1);    stack.push(2);    stack.push(3);    stack.push(4);    stack.push(5);    stack.push(6);    cout<<"size = "<<stack.getSize()<<endl;    stack.print();

输出:

this is a ctor of stacksize = 7m_stack : 0 1 2 3 4 5 6this is a dtor of stack

注意区别一下pop和peek,返回栈顶元素,一个会删除元素,另一个则不做其他操作。

    stack.print();    cout<<"peek : "<<stack.peek()<<endl;    stack.print();    cout<<"pop : "<<stack.pop()<<endl;    stack.print();    cout<<"peek : "<<stack.peek()<<endl;    stack.print();

输出:

m_stack : 0 1 2 3 4 5 6peek : 6m_stack : 0 1 2 3 4 5 6pop : 6m_stack : 0 1 2 3 4 5peek : 5m_stack : 0 1 2 3 4 5

2.单向链表实现栈

定义一个Stack1的类,成员变量为sNode 类型的指针head,int类型的变量count,为栈元素个数。

class Stack1{    public:        Stack1();        ~Stack1();        void push(int data);        int pop();        int peek();        int getSize();        void print();    protected:    private:        sNode *head;        int count;};

具体实现跟数组差不多,给出代码就不详细说了。

Stack1::Stack1(){    //ctor    cout<<"this is a ctor of stack1"<<endl;    head = new sNode();    head->next = NULL;    count = 0;}Stack1::~Stack1(){    //dtor    cout<<"this is a dtor of stack1"<<endl;    while(head->next)    {        sNode *tmp = head->next;        head->next = tmp->next;        delete tmp;        tmp = NULL;        count--;    }    delete head;    head = NULL;}void Stack1::push(int data){    sNode *node = new sNode();    node->data = data;    node->next = head->next;    head->next = node;    count++;}int Stack1::pop(){    int res;    if(head->next)        res = head->next->data;    head->next = head->next->next;    count--;    return res;}int Stack1::peek(){    int res = 0;    if(head->next)        res = head->next->data;    return res;}int Stack1::getSize(){    return count;}void Stack1::print(){    cout<<"m_stack : ";    sNode *tmp = head->next;    while(tmp)    {        cout<<tmp->data<<" ";        tmp = tmp->next;    }    cout<<endl;}

测试代码和结果跟数组也是一样的,就不贴了。

3.STL标准库

如果我们使用C++标准库,用不着费那么大劲去实现栈,它已经给我们封装好了,跟vector一样直接使用,十分方便。

只需要加这么一句:#include <stack>

看下测试代码:

    stack<int> istack;    istack.push(0);    istack.push(1);    istack.push(2);    istack.push(3);    istack.push(4);    istack.push(5);    cout<<"size = "<<istack.size()<<endl;    cout<<"istack : ";    while(!istack.empty())    {        cout<<istack.top()<<" ";        istack.pop();    }    cout<<endl;    if(istack.empty())        cout<<"now stack is empty"<<endl;

输出结果为:

size = 6top : 5istack : 5 4 3 2 1 0now stack is empty

队列

队列(queue)是一种两端开方的线性结构。它在线性表的前端(front),即队首进行删除操作,在表的后端(rear),队尾进行插入操作。因此,它遵循先进先出(First In First Out, FIFO)的方式。

队列的操作主要也是三种:

  • push:入队,向队列末尾添加元素;
  • pop:出队,删除队列开始位置的元素;
  • front:返回队列开始位置的元素。

还是给出队列的几种实现形式。

1.数组实现

在Queue这个类中,主要还是实现下面操作队列的几个方法,大部分跟栈的实现是一样的。

class Queue{    public:        Queue();        ~Queue();        void push(int data);        int pop();        int front();        int getSize();        void print();    protected:    private:        vector<int> m_queue;        int count;};

实现:

Queue::Queue(){    //ctor    cout<<"this is a ctor of queue"<<endl;    count = 0;}Queue::~Queue(){    //dtor    cout<<"this is a dtor of queue"<<endl;}void Queue::push(int data){    m_queue.push_back(data);    count++;}int Queue::pop(){    int res = m_queue.at(0);    int i = 1;    while(i < count)    {        m_queue[i-1] = m_queue[i];        i++;    }    count--;    m_queue.pop_back();    return res;}int Queue::front(){    return m_queue.at(0);}int Queue::getSize(){    return m_queue.size();}void Queue::print(){    cout<<"m_queue : ";    for(vector<int>::iterator i = m_queue.begin(); i != m_queue.end(); i++)    {        cout<<*i<<" ";    }    cout<<endl;}

注意这里的push是添加到数组的末尾,因此pop就要从数组开始进行,因此是m_queue.at(0),然后要将后面的元素依次前移一位,然后删除最后一个元素。

测试:

    Queue queue;    for(int i = 0; i < 6; i++)        queue.push(i);    cout<<"size = "<<queue.getSize()<<endl;    queue.print();    cout<<"front : "<<queue.front()<<endl;    queue.print();    cout<<"pop : "<<queue.pop()<<endl;    queue.print();    cout<<"front : "<<queue.front()<<endl;    queue.print();    cout<<"push : "<<endl;    queue.push(7);    queue.print();

输出:

this is a ctor of queuesize = 6m_queue : 0 1 2 3 4 5front : 0m_queue : 0 1 2 3 4 5pop : 0m_queue : 1 2 3 4 5front : 1m_queue : 1 2 3 4 5push :m_queue : 1 2 3 4 5 7this is a dtor of queue

2.链表实现

链表实现也差不多,代码如下:

struct qNode{    int data;    qNode *next;};class Queue1{    public:        Queue1();        ~Queue1();        void push(int data);        int pop();        int front();        int getSize();        void print();    protected:    private:        qNode *head;        int count;};

方法的实现:

Queue1::Queue1(){    //ctor    cout<<"this is a ctor of queue1"<<endl;    head = new qNode();    head->next = NULL;    count = 0;}Queue1::~Queue1(){    //dtor    cout<<"this is a dtor of queue1"<<endl;    while(head->next)    {        qNode *tmp = head->next;        head->next = tmp->next;        delete tmp;        tmp = NULL;        count--;    }    delete head;    head = NULL;}void Queue1::push(int data){    qNode *node = new qNode();    node->data = data;    node->next = NULL;    qNode *tmp = head;    while(tmp->next)        tmp = tmp->next;    tmp->next = node;    count++;}int Queue1::pop(){    int res = 0;    if(head->next)        res = head->next->data;    head->next = head->next->next;    count--;    return res;}int Queue1::front(){    int res = 0;    if(head->next)        res = head->next->data;    return res;}int Queue1::getSize(){    return count;}void Queue1::print(){    cout<<"m_queue : ";    qNode *tmp = head->next;    while(tmp)    {        cout<<tmp->data<<" ";        tmp = tmp->next;    }    cout<<endl;}

为了操作方便,我们以链表末尾为队列开始位置,链表起始位置为队列开头。这样,需要入队时,需要找到队列的最后一个节点,然后将该节点的next指针指向新增加的节点即可;出队或者输出队首元素时,取head->next的节点就可以了。

测试代码和结果跟数组实现的是一样的。

3.STL标准库

同样,如果我们使用C++标准库,也无需实现队列,而是通过#include <queue>,直接去使用。

测试代码:

    queue<int> iqueue;    for(int i = 0; i < 6; i++)        iqueue.push(i);    cout<<"size = "<<iqueue.size()<<endl;    cout<<"iqueue : ";    while(!iqueue.empty())    {        cout<<iqueue.front()<<" ";        iqueue.pop();    }    cout<<endl;    if(iqueue.empty())        cout<<"now queue is empty"<<endl;

输出:

size = 6iqueue : 0 1 2 3 4 5now queue is empty

本文所有例子见github:下载测试代码