<C/C++数据结构> 栈

一,栈的基本定义

栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。


1、栈的操作

 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
  (1)通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。
  (2)当表中没有元素时称为空栈。
  (3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表。
 栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除。


2,栈的示图

元素是以a1,a2,…,an的顺序进栈,退栈的次序却是an,an-1,…,a1。



二,数组实现栈(C++模板)

1,stack.h的实现:

#include "iostream"
#include "windows.h"
using namespace std;
template<typename DataType> 
class MyStack
{
public:
	MyStack(int size)
	{
		maxSize = size;                   //设置最大容量
		top = -1;                         //初始化为空栈
		elements = new DataType[size];    //动态分配连续的数组空间,共size个数据
		for (int i=0;i<maxSize;i++)
		{
			elements[i]=0;
		}
		
	}

	~MyStack()
	{
		if (elements!=NULL)
		{
			delete[] elements;
			elements=NULL;
		}
	}
	//入栈操作
	bool push(DataType data);
	//出栈操作
	DataType pop();
	//判断栈是否为空
	bool IsEmpty();
	//获取元素个数
	int GetNums();
	//摧毁栈
	void DestroyStack();
	//求取栈中的最小值
	DataType Min();
	//求取栈中的最大值
	DataType Max();
private:
	DataType *elements;           //数据域指针
	int top;                     //栈顶,top=0,就表示有一个数据了
	int maxSize;                 //栈的最大容量
};

/*****************入栈操作************************/
template<typename DataType> 
bool MyStack<DataType>::push(DataType data)
{
	if((top+1) == maxSize)                     //入栈前一定要先判断是否栈满
	{
		cout<<"已经满栈!此时栈顶为"<<data<<endl;
		return false;
	}
	else
	{
		top++;
		elements[top] = data;     //从栈顶压入元素,并且top加一
	}
	return true;
}

/********************出栈操作(去元素)*******************/
template<typename DataType> 
DataType MyStack<DataType>::pop()
{
	if(IsEmpty())                          //判断是否栈空
	{
		cerr<<"栈为空,注意检查"<<endl;
		exit(1);
	}
	else
	{
		return elements[top--];                //返回当前栈顶元素,随后top减一
		//top--;
	}
}

/*************************栈判断是否空***********************/
template<typename DataType>
bool MyStack<DataType>::IsEmpty()
{
	if(top == -1)
		return true;
	else
		return false;
}

/*********************获取当前元素个数数********************/
template<typename DataType> 
int MyStack<DataType>::GetNums()
{
	if(top >= 0)
		return top+1;
	else
		return 0;
}

template<typename DataType> 
void MyStack<DataType>::DestroyStack()
{
	maxSize = 0;                   //设置最大容量
	top = 0;                         //初始化为空栈
	delete[] elements ;    //动态分配连续的数组空间,共size个数据
	elements=NULL;
}

template<typename DataType> 
DataType MyStack<DataType>::Min()//直接遍历的方法求最小值(或者最大值)
{
	DataType temp=elements[0];
	for (int i = 1;i < top+1;i++)
	{
		if (elements[i] < temp)
		{
			temp=elements[i];
		}
	}
	return temp; 
}

template<typename DataType> 
DataType MyStack<DataType>::Max()
{
	DataType temp=elements[0];
	for (int i = 1;i < top+1;i++)
	{
		if (elements[i] > temp)
		{
			temp=elements[i];
		}
	}
	return temp; 
}


2,主测试代码:

// ConsoleAppStack.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Stack.h"
#include "iostream"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	//首先按顺序入栈 
	MyStack<int> s = MyStack<int>(10);               //创建栈结构,这个栈可以容纳10个元素  
	//入栈  
	s.push(10);  
	s.push(15);  
	s.push(1);  
	s.push(6);  
	s.push(45);  
	s.push(9);  
	s.push(35);  
	cout<<"当前栈中元素个数为:  "<<s.GetNums()<<endl;  
	int temp = s.pop();
	cout<<"栈顶元素出栈: "<<temp<<endl;
	cout<<"当前栈中元素个数为:  "<<s.GetNums()<<endl;  
	cout<<"栈的最小值"<<s.Min()<<endl;
	cout<<"栈的最大值"<<s.Max()<<endl;
	s.DestroyStack();
	cout<<"栈已经摧毁!"<<endl;
	system("pause");
	return 0;  
}


3,测试结果:


 

三,链表实现栈(C++模板)

1,StackLink.h的实现:

#include "stdafx.h"
#include "iostream"
using namespace std;

template<class DataType> class Stack;

template<class DataType>
class LinkNode
{
public:
	LinkNode()
	{
		next=NULL;
		nData=0;
	}

	LinkNode(DataType newData)
	{
		next=NULL;
		nData=newData;
	}

	~LinkNode()
	{

	}
private:
	friend class Stack<DataType>;
	LinkNode<DataType> *next;
	DataType nData;
};

template<class DataType>
class Stack
{
public:
	Stack(int size)
	{
		top=NULL;
		count=0;
		maxSize=size;
	}
	~Stack()
	{
		int len=getNum();
		for ( int i=0;i< len;i++)
		{
			LinkNode<DataType> *p=top;
			top=p->next;
			delete p;
		}
	}
	int getNum()
	{
		return count;
	}
	//进栈
	bool InsertNode(DataType newData);
	//出栈
	bool outNode();
private:
	LinkNode<DataType> *top;
	int count;
	int maxSize;
};

template<class DataType>
bool Stack<DataType>::InsertNode(DataType newData)
{
	if (getNum() == maxSize)
	{
		cerr<<"栈已经满,请勿再进行插入操作!"<<endl;
		return false;
	}else
	{
		LinkNode<DataType> *newNode=new LinkNode<DataType>(newData);
		if (top == NULL)
		{
			top=newNode;
			count++;
			return true;
		}else
		{
			newNode->next=top;
			top=newNode;
			count++;
			return true;
		}
	}
}


template<class DataType>
bool Stack<DataType>::outNode()
{
	if (getNum() == 0)
	{
		cerr<<"数据已经全部出栈,请勿再继续操作!"<<endl;
		return false;
	}
	else
	{
		LinkNode<DataType> *p=top;
		cout<<"当前出栈数据为"<<p->nData<<endl;
		top=p->next;
		delete p;
		count--;
		return true;
	}
}

2,主测试代码如下:

// ConsoleAppStackList.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "StackList.h"
#include "iostream"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	int len=10;
	Stack<char> S(len);
	char str='A';
	for (int i = 0;i < len;i++)
	{
		S.InsertNode(str++);
	}
	cout<<"当前栈中数据个数为:"<<S.getNum()<<endl;
	cout<<"--------------栈初始化已经完成---------------"<<endl;
	for (int j=0; j<11;j++)
	{
		if (S.getNum() == 0)
		{
			cerr<<"数据已经全部出栈,操作即将停止!"<<endl;
			break;
		}
		S.outNode();
	}
	system("pause");
	return 0;
}

3,测试结果:





四,小试牛刀

1,括号匹配问题

题目描述:

    在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注.

输入:

    输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100。
    注意:cin.getline(str,100)最多只能输入99个字符!

输出:

    对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$","?"和空格组成,"$"和"?"表示与之对应的左括号和右括号不能匹配。

样例输入:
)(rttyy())sss)(
样例输出:
)(rttyy())sss)(
?            ?$


#include "iostream"  
#include "string"  
#include "stack"  
 
using namespace std;
 
void BracketMatch(const string srcStr);
int main()
{
    string str;
    while (cin >> str)
    {
        cout << str << endl;
        BracketMatch(str);
    }
    return 0;
}
 
void BracketMatch(const string srcStr)
{
    stack<int> s;
    string ansStr(srcStr.length(),'0');
    for (unsigned int i = 0; i < srcStr.length(); i++)//从左往右开始遍历  
    {
        if (isalpha(srcStr[i]))
        {
            ansStr[i]=' ';
            continue;
        }
        switch (srcStr[i])
        {
                //对左括号仅作压栈处理,也就是说栈中只可能是左括号  
            case '(':
                if (i != (srcStr.length() - 1))//当是最后一个字符时已经没有必要输出空格了
                    ansStr[i] = ' ';
                s.push(i);//注意,这里
                break;
 
                //对右括号做匹配判断
            case ')':
                if (!s.empty())
                {//如果不为空,说明一定有左括号(实际上是其数组下标)
                    s.pop();
                    ansStr[i] = ' ';
                }
                else//如果为空
                    ansStr[i] = '?';
                break;
 
            default:
                cerr << "错误的括号" << endl;
        }
    }
    while (!s.empty())
    {  //解决多余的左括号  
        ansStr[s.top()] = '$';
        s.pop();
    }
    cout << ansStr << endl;
}



注:

本文部分文字学习并copy自网络,代码参考并改编自《算法导论》.

如果侵犯了您的版权,请联系本人tangyibiao520@163.com,本人将及时编辑掉!


参考资源:

【1】《百度文库》

【2】《算法导论》


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C/C++ 是应用广泛的编程语言,其在数据结构应用方面也十分重要。面试中相关的 C/C++ 数据结构问题主要围绕数组、链表、二叉树和图等方面。以下是一些常见问题及其解答: 1. 如何反转一个单向链表? 答:可以使用三个指针来实现:cur 代表当前节点,pre 代表上一个节点,next 代表下一个节点。每次遍历时,将 cur 的 next 指向 pre,然后将三个指针分别向后移动即可。 2. 如何判断两个链表是否相交,并找出相交的点? 答:可以分别遍历两个链表,得到各自的长度。然后让长的链表先走 n 步,使得两个链表剩余的长度相等。接下来同时遍历两个链表,比较节点是否相同即可找出相交的点。 3. 如何判断一个二叉树是否为平衡二叉树? 答:可以计算每个节点的左右子树深度差,如果任何一个节点的深度差大于1,则此树不是平衡二叉树。可以使用递归实现,每次计算当前节点的深度,然后递归判断其左右子树是否平衡。 4. 如何实现图的深度优先搜索(DFS)和广度优先搜索(BFS)算法? 答:DFS 可以使用递归实现。从某个节点开始,逐个访问其未被访问的邻接节点,并将其标记为已访问。然后对每个未被访问的邻接节点递归调用 DFS 函数。BFS 可以使用队列实现。从某个节点开始,将其加入队列,并标记为已访问。然后从队列中弹出节点,并访问其所有未被访问的邻接节点,并将其加入队列中。重复此过程直到队列为空。 以上是一些常见的 C/C++ 数据结构面试问题及其解答。在面试中,除了掌握相关算法和数据结构知识外,还需多做练习和积累经验,才能更好地应对各种面试问题。 ### 回答2: C语言是一种用于编写系统级程序的高级编程语言,具有简单、高效、灵活等特点,是许多操作系统、编译器等软件的首选语言,也是许多企业在进行面试时重点考察的技能。在C/C++数据结构面试题中,经常会涉及到各种数据结构相关的算法和应用,测试面试者的算法思维能力和实现能力。 其中,常见的数据结构包括链表、和队列、二叉树、搜索树、哈希表等。在面试时,会常常涉及代码设计和实现,比如实现链表的插入、删除、查找操作,实现二叉树的遍历、查找操作等。 此外,在数据结构面试中,还经常涉及排序和查找算法,如冒泡排序、快速排序、归并排序、二分查找、哈希查找等。同时,面试者还需要解决一些较为复杂的算法问题,如图的最短路径问题,最小生成树问题等。 总之,C/C++数据结构面试题涵盖了运用数据结构的各种算法和实现方法,需要面试者具备扎实的编程基础和算法思维能力。在备战面试时,可以多做练习,熟悉常用的数据结构和算法,提高理解和实现能力,从而更好地应对面试挑战。 ### 回答3: 面试过程中常见的C/C++数据结构面试题有很多。以下就介绍几个常见的题目并给出解答。 1. 求两个有序数组的中位数 题目描述:给定两个升序排列的整形数组,长度分别为m和n。实现一个函数,找出它们合并后的中位数。时间复杂度为log(m+n)。 解答:这个问题可以使用二分法求解。首先,我们可以在两个数组中分别选出所谓的中间位置,即(i+j)/2和(k+l+1)/2,其中i和j分别是数组A的起始和结束位置,k和l分别是数组B的起始和结束位置。判断A[i+(j-i)/2]和B[k+(l-k)/2]的大小,如果A的中间元素小于B的中间元素,则中位数必定出现在A的右半部分以及B的左半部分;反之,则必定出现在A的左半部分以及B的右半部分。以此类推,每一次都可以删去A或B的一半,从而达到对数级别的时间复杂度。 2. 堆排序 题目描述:对一个长度为n的数组进行排序,时间复杂度为O(nlogn)。 解答:堆排序是一种常用的排序算法,在面试中也经常被考察。堆排序的具体过程是首先将数组构建成一个最大堆或最小堆,然后不断将堆顶元素与最后一个元素交换,并将最后一个元素从堆中剔除。这样,每次剔除后,堆都会重新调整,使得剩下的元素仍然保持堆的性质,直到堆中只剩下一个元素为止。 3. 链表反转 题目描述:反转一个单向链表,例如给定一个链表: 1->2->3->4->5, 反转后的链表为: 5->4->3->2->1。 解答:链表反转题目也是非常常见,其思路也比较简单。遍历链表,将当前节点的next指针指向前一个节点,同时记录当前节点和前一个节点,直至遍历到链表末尾。 以上这三个问题分别从二分法、堆排序和链表三个方面介绍了常见的C/C++数据结构面试题,希望能帮助面试者更好地准备面试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值