模板(顺序表与栈)

”顺序表与栈“

顺序表相对于我们来说已经不算是陌生的,顺序表有自己独有的特点,需要有一块独有的空间,访问中间的数据也较为简单,插入和删除数据就相对较难。针对顺序表的特点,我们不难想到一个数据结构“栈”,栈的特点与顺序表相对来说很接近,栈的主要特点是”先进后出“,即就是后进入栈的数据必须先出才能够访问到先前进入的数据,用顺序表来实现“栈”的一些基本功能更加合适。

这里首先提一下“模板”的概念,模板的一般形式为template<class 形参名1, class 形参名2> ;模板的实例化为:

template <typename T>      //这里也可以用class
bool IsEqual(const T& left, const T& right)
{
         return left == right;
}

void test1()
{
        cout << IsEqual<int>(1, 1.2) << endl;
}

下面主要是利用模板来实现顺序表,这样的好处在于可以针对各种的数据类型,避免了直接将顺序表中的数据类型进行限制,局限性降低。同时利用顺序表的功能来实现栈,下面是用模板来实现顺序表:

#pragma once
//顺序表
template <class T>
class SeqList
{
public:
    SeqList()     //无参构造函数
       :_array(NULL)
       , _size(0)
       , _capacity(0)
    { }
    
    SeqList(const SeqList<T>& x)    //拷贝构造函数
       :_array(new T[x._size])
       , _size(x._size)
       , _capacity(x._size)
    {
        //memcpy(_array, x._array, sizeof(T)*(x._size));
        if (_array)
        {
            for (int i = 0; i < x._size; i++)
            {
                _array[i] = x._array[i];
            }
        }
    }
    
    ~SeqList()     //析构函数
    {
        if (_array)
        {
            delete[] _array;
         }
    }
    
    SeqList<T>& operator=(SeqList<T>& x)      //赋值运算符重载
    {
        if (this != &x)
       {
           SeqList * tmp = new T[x._size];
           delete[] _array;
           _array = tmp;
           _size = x._size;
           _capacity = x._size;
           memcpy(_array, x._array, sizeof(T)*(x._size));
       }
       return *this;
    }
    
    SeqList<T> & operator[](size_t index)
    {
        assert(index < _size);
        return _array[index];
    }
    
public:
    void pushBack(const T& x)    //尾插
    {
        _checkCapacity(_size + 1);
        _array[_size++] = x;
    }
    
     void popBack()     //尾删
     {
         if (_size <= 0)
         {
             return;
         }
         else
        {
             _array[_size - 1] = NULL;
             _size--;
         }
     }
     
     void pushFront(const T& x)     //头插
     {
         _checkCapacity(_size + 1);
         for (int i = 0; i < _size; i++)
         {
             _array[_size - i] = _array[_size - 1 - i];
         }
         _array[0] = x;
         _size++;
     }
     
     void popFront()    //头删
     {
         if (_size)
         {
             for (int i = 0; i < _size; i++)
             {
                 _array[i] = _array[i + 1];
              }
          }
          _size--;
     }
     
     void Insert(size_t pos, const T &x)   //任何位置插入
    {
        if (pos < 0 || pos > _size)
        {
            return;
        }
         else
        {
            for (int i = _size; i > pos; i--)
            {
                _array[i] = _array[i - 1];
            }
             _array[pos] = x;
             _size++;
        }
    }
    
     void Erase(size_t pos)    //删除pos位置的数据
    {
        if (pos < 0 || pos > _size)
        {
            return 0;
        }
        else
        {
            for (int i = pos; i < _size; i++)
            {
                _array[i - 1] = _array[i];
             }
             _size--;
        }
    }
    
     int Find(T & x)    //查找
    {
        for (int i = 0; i < _size; i++)
        {
            if (x == _array[i])
            {
                return i + 1;
             }
         }
        if (i >= _size)
        {
             return 0;
        }
    }
    
     void print()   //格式输出
    {
        for (int i = 0; i < _size; i++)
       {
            cout << _array[i] << " ";
       }
        cout << endl;
    }

     void _checkCapacity(size_t n)    //检查容量
    {
        if (n > _capacity)
        {
             _capacity = n > 2 * _capacity + 3 ? n : (2 * _capacity + 3);
            //不能直接用realloc来增容,realloc不会调用构造函数,
            //不能对其空间进行初始化,而new可以直接调用构造函数
            T * tmp = new T[_capacity];
            if (_array)
           {
               for (int i = 0; i < _size; i++)
               {
                   tmp[i] = _array[i];
                }
               delete[] _array;
           }
           _array = tmp;
        }
    }

     size_t Size()
     {
         return _size;
     }
     
     T& Top()
     {
         return _array[_size-1];
      }

private:
     T* _array;
     int _size;
     int _capacity;
};

下面是“栈”的基本功能实现:

#pragma once
#include <assert.h>
#include "SeqList.h"
//栈
template <class T, class container = SeqList<T>>
class Stack
{
public:
     void push(const T & x)     //压栈
     {
         _con.pushBack(x);
     }
     
      void pop()      //出栈
     {
         _con.popBack();
     }
     
      bool Empty()      //判空
     {
         return _con.Size() == 0;
     }
     
     size_t size()    //计算元素个数
    {
         return _con.Size();
     }
     
     T & top()        //读取栈顶元素
    {
        return _con.Top();
     }
private:
    container _con;
};
时间: 2025-01-01 12:08:29

模板(顺序表与栈)的相关文章

顺序表实现栈

/*  使用顺序表存储栈的过程,同时使用了remalloc函数   对于顺序栈满的情况进行了扩展,是将原先的数据拷贝   过来,然后进行增长 */ #define STACK_INIT_SIZE 3  //顺序栈的初始化分配空间 #define STACK_INCREASE_SIZE 6//顺序栈的分配增量 typedef struct SStackNode {     int nStackElement;     SStackNode* pNextNode; }SStackNode; clas

顺序表、栈与队列

一.顺序表引入 1什么是线性表 1 在程序中,经常需要将一组数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等. 2 一组数据中包含的元素个数可能发生变化(增加或删除元素). 3 对于这种需求,最简单的解决方案便是将这样一组元素看成一个序列,用元素在序列里的位置和顺序,表示实际应用中 的某种有意义的信息,或者表示数据之间的某种关系. 4 这样的一组序列元素的组织形式,我们可以将其抽象为线性表. 5 一个线性表是某类元素的一个集合,还记录着元素之间的一种顺序关系. 6

C++基于模板顺序表的实现(带排序)

说明:代码是可以运行的,但是发表在博客上后复制到编译器里面报N多错误,找了半天原因是网页里面生成了一些空白字符,这些字符编译器无法识别. 因此使用了2种插入格式插入代码. 第一个带注释解释的代码不可复制,最下面的第二个代码可以正常复制 代码如下: #include <iostream> #include<cstdlib> //rand()函数产生随机值 #include<string> //bool函数赋值 #include<iomanip> //输出格式控

C++模板实现动态顺序表(更深层次的深浅拷贝)与基于顺序表的简单栈的实现

前面介绍的模板有关知识大部分都是用顺序表来举例的,现在我们就专门用模板来实现顺序表,其中的很多操作都和之前没有多大区别,只是有几个比较重要的知识点需要做专门的详解. 1 #pragma once 2 #include<iostream> 3 #include<string> 4 #include<stdlib.h> 5 using namespace std; 6 7 template <class T> 8 class Vector 9 { 10 publ

模板实现顺序表

类模板的成员函数: 类模板的成员函数本身是一个普通函数.但是,类模板的每个实例都有其自己版本的成员函数.因此,类模板的成员函数具有和模板相同的模板参数.因此,在=定义在类模板之外的成员函数就必须以template开始,后跟类模板参数列表. 类模板中的友元函数: 类模板中的友元函数,应该在类中定义.若只在类中声明,在类外定义,则在链接时会出现错误. 类模板实现顺序表: "SeqList.h" //冒泡法 "test.cpp"

C++顺序表模板练习 以及 剖析易出现的浅拷贝问题

/* C++顺序表模板练习 以及 剖析易出现的浅拷贝问题 */ #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <string> using namespace std; template <typename T> class SeqList { public: SeqList(); SeqList(const SeqList& s); ~SeqList(); void PushBac

动态顺序表 与 双向链表的模板类

//////////////////////////////////////////////////////////////////////// /////////////////////泛型编程之动态顺序表的模板///////////////////////// //////////////////////////////////////////////////////////////////////// #include<iostream> #include<string> u

C++的标准模板库STL中实现的数据结构之顺序表vector的分析与使用

摘要 本文主要借助对C++的标准模板库STL中实现的数据结构的学习和使用来加深对数据结构的理解.即联系数据结构的理论分析和详细的应用实现(STL),本文是系列总结的第一篇,主要针对线性表中的顺序表(动态数组)STL vector进行分析和总结. 引言 因为前段时间对台大的机器学习基石和技法课程进行了学习,发如今详细的实现中经常涉及到各种类型的数据结构,比方线性表.二叉树.图等,在使用这些数据结构时感到有些吃力.主要是对一些主要的数据结构理解的不够.所以趁着暑假假期.近期一段时间总会抽出时间复习一

数据结构回顾之顺序存储结构中的线性表(栈与队列顺序线性表实现)

说到数据结构呢,对于一个Coder来说还是蛮重要的啦,每次看数据结构的东西都有新的收获,这两天在回顾数据结构的知识.当然啦,虽然数据结构有些是理论的东西,如果好好的理解数据结构的东西还是少不了的代码的支撑的.数据结构简单的来说吧,可以分为两大类,一个是数据的"物理存储结构",另一种是数据的"逻辑存储结构".数据的"物理存储结构"又可分为顺序的和链式的(下面将会结合着代码打印内存地址的形式来观察物理存储结构). 逻辑存储结构又可分为集合,线性, 树