数据结构面试之三——栈的常见操作

简介: 1.基于数组的栈的三要素:1)栈的最大容量maxSize; 2)栈的当前容量=当前栈中元素的个数=栈顶top-1;3)动态数组存储栈的元素 Type* list; 2.对于出栈、入栈的操作要对应先判断栈空、栈满;如果空、满要有异常处理或错误提示。

数据结构面试之三——栈的常见操作

题注:《面试宝典》有相关习题,但思路相对不清晰,排版有错误,作者对此参考相关书籍和自己观点进行了重写,供大家参考。


三、栈的基本操作


3.1用数组构造栈


【注意以下几点】:


1.基于数组的栈的三要素:1)栈的最大容量maxSize; 2)栈的当前容量=当前栈中元素的个数=栈顶top-1;3)动态数组存储栈的元素 Type* list;


      2.对于出栈、入栈的操作要对应先判断栈空、栈满;如果空、满要有异常处理或错误提示。


      3.注意入栈push操作,先入栈后top+1;出栈pop则相反,先top-1,再出栈。【注意因为,top指向数组中最后一个元素的下一个位置】。


      4.拷贝构造函数和赋值函数要注意,尤其赋值的时候,避免自身赋值、同时要注意大小不一致的不能完成赋值操作,要有相关提示。


   


template<typenameType>

class arrStack

{

public:

      arrStack(intnSize=100);

      ~arrStack();

      arrStack(constarrStack& copyStack);

      arrStack&operator=(const arrStack& otherStack);

      voidinitializeStack();

      void destroyStack();

      bool isStackEmpty();

      bool isStackFull();

      void push(constType& item);

      void pop(Type&poppedItem);

private:

      int maxSize;

      int top;

      Type* list;

};

template<typename Type>

arrStack<Type>::arrStack(int nSize=100)

{

      if(nSize < 0)

      {

             nSize = 100;

             list = newType[nSize];

             top = 0;

             maxSize = 100;

      }

      else

      {

             list = newType[nSize];

             top = 0;

             maxSize =nSize;

      }

}

template<typename Type>

arrStack<Type>::~arrStack()

{

      if(!list)

      {

             delete[]list;                //注意数组的删除,为delete []list;

             list = NULL;

      }

}

template<typename Type>

arrStack<Type>::arrStack(const arrStack& copyStack)

{

      maxSize =copyStack.maxSize;

      top = copyStack.top;

      list = newType[maxSize];           //注意需要自定义大小,容易出错.

      for( int i = 0; i <top; i++)

      {

             list[i] =copyStack.list[i];

      }

}

template<typename Type>

arrStack<Type>& arrStack<Type>::operator=(constarrStack& otherStack)

{

      if(this ==&otherStack)

      {

             cout <<"can't copy oneSelf!" << endl;

             return *this;

      }

      else

      {

             if(maxSize !=otherStack.maxSize)

             {

                    cout<< "The Size of two stack are not equal!" << endl;

                    return*this;

             }

             else

             {

                    maxSize= otherStack.maxSize;

                    top =otherStack.top;

                    for( inti = 0; i < top; i++)

                    {

                           list[i]= otherStack.list[i];

                    }//endfor

                    return*this;

             }

      }//end else

}

template<typename Type>

void arrStack<Type>::initializeStack()

{

      destroyStack();

}

template<typename Type>

void arrStack<Type>::destroyStack()

{

      top = 0;

}

template<typename Type>

bool arrStack<Type>::isStackEmpty()

{

      return (top == 0);

}

template<typename Type>

bool arrStack<Type>::isStackFull()

{

      return (top ==maxSize);

}

template<typename Type>

void arrStack<Type>::push(const Type& item)

{

      if(!isStackFull())

      {

             list[top] =item;

             top++;

      }

      else

      {

             cout <<"The Stack was already Full!" << endl;

      }

}

template<typename Type>

void arrStack<Type>::pop(Type& poppedItem)

{

      if(!isStackEmpty())

      {

             top--;

             poppedItem =list[top];

      }

      else

      {

             cout <<"The Stack was already Empty!" << endl;

      }

}

3.2用链表构造栈


链表构造栈注意:


1) 判断栈空的标记是top==NULL;由于栈的空间可以动态分配,因此可以认为链栈不会满。


2) 栈的入栈Push操作要先判定栈是否已经满,非满才可以入栈。先入栈,再调整top指针;


3) 栈的出栈Pop操作要先判定栈是否已空,非空才可以出栈。先调整top指针,再出栈,并删除原结点。


4) 可以加count判定当前结点的个数。



template<typename Type>

struct nodeType

{

      Type info;

      nodeType* link;

};

template<typename Type>

class linkedStack

{

public:

      linkedStack();

      ~linkedStack();

      linkedStack(constlinkedStack<Type>&);

      linkedStack&operator=(const linkedStack<Type>&);

      voidinitializeStack();

      void destroyStack();

      bool isStackEmpty()const;

      bool isStackFull()const;

      void push(constType& item);

      void pop(Type&poppedItem);

      void nodeCount();

   

      voidreversePrint();          //逆向打印的非递归实现...

private:

      nodeType<Type>*top;

      int count;         //统计节点个数

};

template<typename Type>

linkedStack<Type>::linkedStack()

{

      count = 0;

      top = NULL;

}

template<typename Type>

linkedStack<Type>::~linkedStack()

{

      while( top != NULL )

      {

             nodeType<Type>*tempNode = new nodeType<Type>;

             tempNode = top;

             top =top->link;

             deletetempNode;

      }//end if

}

template<typename Type>

linkedStack<Type>::linkedStack(constlinkedStack<Type>& copyStack)

{

      if(copyStack.top !=NULL)

      {

             nodeType<Type>*current;

             nodeType<Type>*first;

             nodeType<Type>*newNode;

         

             top = newnodeType<Type>;

             top->info =copyStack.top->info;                //此处的top不能直接用,内存报错!

             top->link =copyStack.top->link;

             first =top;                        //first跟进当前链表...

             current =copyStack.top->link;      //current跟进copy链表...

             while( current!= NULL)

             {

                    newNode= new nodeType<Type>;

                    newNode->link= current->link;

                    newNode->info= current->info;

                    first->link= newNode;

                    first =newNode;

                    current= current->link;

             }//end while

             count =copyStack.count;

      }//end if

      else

      {

             top = NULL;

             count = 0;

      }

}

template<typename Type>

linkedStack<Type>&linkedStack<Type>::operator=(const linkedStack<Type>&otherStack)

{

      //1避免自身赋值

      if(this ==&otherStack)

      {

             cout <<"Can't copy oneself!" << endl;

             return *this;

      }

      //2其他

      else

      {

             if(top != NULL)

             {

                    destroyStack();

             }

             if(otherStack.top!= NULL)

             {

                    nodeType<Type>*current;

                    nodeType<Type>*first;

                    nodeType<Type>*newNode;

                    top =new nodeType<Type>;

                    top->info= otherStack.top->info;

                    top->link= otherStack.top->link;

                    first =top;                        //first跟进当前链表...

                    current= otherStack.top->link;      //current跟进copy链表...

                    while(current != NULL)

                    {

                           newNode= new nodeType<Type>;

                           newNode->link= current->link;

                           newNode->info= current->info;

                           first->link= newNode;

                           first= newNode;

                           current= current->link;

                    }//endwhile

                    count =otherStack.count;

             }//end if

             else

             {

                    top =NULL;

                    count =0;

             }

             return *this;

      }

}

template<typename Type>

void linkedStack<Type>::initializeStack()

{

      destroyStack();

}

template<typename Type>

void linkedStack<Type>::destroyStack()

{

      count = 0;

      top = NULL;

}

template<typename Type>

bool linkedStack<Type>::isStackEmpty() const

{

      return (count == 0);

}

template<typename Type>

bool linkedStack<Type>::isStackFull() const //空间非固定,动态申请!

{

      return false;

}

template<typename Type>

void linkedStack<Type>::push(const Type& item)

{

      if(!isStackFull())

      {

             nodeType<Type>*newNode = new nodeType<Type>;

             newNode->info= item;

             newNode->link= NULL;

             if(top == NULL)

             {

                    top = newNode;

             }

             else

             {

                    newNode->link= top;

                    top =newNode;

             }

             count++;

             cout <<item << " was pushed!" << endl;

      }

}

template<typename Type>

void linkedStack<Type>::pop(Type& poppedItem)

{

      if(!isStackEmpty())

      {

             nodeType<Type>*temp = new nodeType<Type>;

             temp = top;

             poppedItem =top->info;

             top =top->link;

         

             count--;

             cout <<poppedItem << " was popped!" << endl;

             delete temp;

      }

}

template<typename Type>

void linkedStack<Type>::nodeCount()

{

      cout <<"nodeCount = " << count << endl;

}

//上一节的递归实现逆向链表打印,这是非递归的实现。

template<typename Type>

void linkedStack<Type>::reversePrint()          //逆向打印的非递归实现...

{

//  注释部分可作为链表调用栈的非递归实现。

//    nodeType<Type>*current = new nodeType<Type>;

//    current = top;

//    while(current != NULL)

//    {

//           pop(current->info);

//           current =current->link;

//    }

      int poppedItem = 0;

      while(!isStackEmpty())

      {

             pop(poppedItem);

      }


相关文章
|
8天前
数据结构——栈和队列
数据结构——栈和队列
10 1
|
11天前
|
存储 算法 调度
数据结构与算法-栈篇
数据结构与算法-栈篇
13 3
|
23小时前
|
存储 JavaScript 前端开发
JavaScript中的数组是核心数据结构,用于存储和操作序列数据
【6月更文挑战第22天】JavaScript中的数组是核心数据结构,用于存储和操作序列数据。创建数组可以使用字面量`[]`或`new Array()`。访问元素通过索引,如`myArray[0]`,修改同样如此。常见方法包括:`push()`添加元素至末尾,`pop()`移除末尾元素,`shift()`移除首元素,`unshift()`添加到开头,`join()`连接为字符串,`slice()`提取子数组,`splice()`进行删除、替换,`indexOf()`查找元素位置,`sort()`排序数组。还有其他如`reverse()`、`concat()`等方法。
7 2
|
3天前
|
NoSQL Java Redis
如何在 Java 中操作这些 Redis 数据结构的基本方法
如何在 Java 中操作这些 Redis 数据结构的基本方法
9 2
|
2天前
|
C++
【洛谷 P1044】[NOIP2003 普及组] 栈 题解(递归+记忆化搜索)
**NOIP2003普及组栈问题**:给定操作数序列1到n,仅允许push(进栈)和pop(出栈)操作。目标是计算所有可能的输出序列总数。输入包含一个整数n(1≤n≤18)。示例输入3,输出5。当队列空时返回1,栈空则只能入栈,栈非空时可入栈或出栈。AC C++代码利用记忆化搜索求解。
5 1
|
4天前
|
算法
$停车场管理系统 栈与队列
$停车场管理系统 栈与队列
5 1
|
8天前
|
存储 算法 程序员
【C++进阶】深入STL之 栈与队列:数据结构探索之旅
【C++进阶】深入STL之 栈与队列:数据结构探索之旅
16 4
|
8天前
数据结构 栈 / 队列(第9天)
数据结构 栈 / 队列(第9天)
|
11天前
数据结构初阶 栈
数据结构初阶 栈
11 1
|
1天前
|
缓存 调度
栈和队列的区别
栈和队列的区别
5 0

热门文章

最新文章