欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构算法之栈

程序员文章站 2022-05-23 11:21:42
...

1.栈的定义与操作

1.1 定义

  1. 定义;即插入操作和删除操作都只能在一端实现,且要求Last in First out来实现的线性表;
  2. 实现:顺序表和单链表

1.2 栈的操作

1.入栈操作:只能将数据元素插入栈顶
2. 出栈操作:移除栈顶的数据元素
3. 获取栈顶元素:获得栈顶的元素
4. 是否为空:
5. 获得栈深:
6. 清空操作:

插曲:递归函数

定义:函数在定义函数内部调用自身,这个函数就是递归函数;

2 练习部分

练习1:进制转换:十进制转换八进制

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"  //文件包含栈操作的实现
void main(){


	// 输出一个非负十进制整数,输出一个等值的八进制整数
	STACK* s;
	s = createStack(8);    //栈的创建
	
	//输入要转换的数
	int N;
	printf("请输入一个整数:\n");
	scanf("%d",&N);
	while(N){
		push(N%8, s);
		N = N / 8;
	}

	int e;
	while(!isEmpty(s)){
		e = topAndTop(s);    //出栈并返回栈顶元素
		printf("%d",e);
	}
	printf("\n");

	//组合操作实现;
}

练习2:火车车厢排序问题
描述:讲一个无序的火车车厢,进入入轨处,通过缓冲轨,结果在出轨处实现正确的递增顺序;
代码实现:

#include <iostream>
using namespace std;

template<class T>
class My_stack;

template<class T>
class Node		//结点类
{
private:
	T data;
	Node<T> *next;
public:
	Node()
	{
		next=NULL;
	}
	Node(T d)
	{
		data=d;
		next=NULL;
	}
	friend My_stack<T>;
};

template<class T>
class My_stack
{
private:
	Node<T> *head;
public:
	My_stack()
	{
		head=new Node<T>();
	}
	
	bool empty() const
	{
		return (head->next==0);
	}
	
	void push(T d)	//入栈
	{
		Node<T> *p=new Node<T>(d);
		p->next=head->next;
		head->next=p;
	}
	
	T top()	//返回栈顶元素
	{
		if(empty())
		{
			cout<<"stack is empty."<<endl;
			exit(1);
		}
		Node<T> *p=head->next;
		T temp=p->data;
		return temp;
	}
	
	void pop()	//弹出栈顶元素
	{
		Node<T> *p=head->next;
		head->next=p->next;
		delete p;
	}
	
};

void OutPut(int& minH,int& minS,My_stack<int> H[],int k,int n);
bool Hold(int c,int& minH,int& minS,My_stack<int> H[],int k,int n);

bool Rail_Road(int p[],int n,int k)
{
	//k个缓冲轨,车厢初始排序为p[1...n]
	
	//创建与缓冲轨对应的链栈
	My_stack<int> *H;
	H=new My_stack<int>[k];
	
	int NowOut=1; //下一次要出轨的车厢
	int minH=n+1; //缓冲轨中编号最小的车厢
	int minS=k; //编号最小的车厢所在缓冲轨的编号

	//车厢重排序
	for(int i=0;i<n;i++)
	{
		if(p[i]==NowOut)
		{
			cout<<"Move car "<<p[i]<<" from input to output"<<endl;
			NowOut++;
			
			//从缓冲轨中输出
			while(minH==NowOut)
			{
				OutPut(minH,minS,H,k,n);
				NowOut++;
				if(NowOut==n+1) //输出全部车厢后返回,不然会造成内存非法访问
					return true;
			}
		}
		else
		{
			//将p[i]放入某个缓冲轨
			if(!Hold(p[i],minH,minS,H,k,n))
				return false;
		}
	}
	return true;
}

void OutPut(int& minH,int& minS,My_stack<int> H[],int k,int n)
{
	//该函数实现把一节车厢从缓冲轨送至出轨处
	//同时修改minH minS的值

	int c;

	//从栈中pop掉编号最小的车厢minH
	c=H[minS].top();
	H[minS].pop();

	cout<<"Move car "<<c<<" from holding track "<<minS+1<<" to output "<<endl;

	//检查所有链栈,搜索新的minH minS
	minH=n+1;
	
	for(int i=0;i<k;i++)
		if( (!H[i].empty()) && (H[i].top()<minH) )
		{
			minH=H[i].top();
			minS=i;
		}
}

bool Hold(int c,int& minH,int& minS,My_stack<int> H[],int k,int n)
{
	//该函数是将车厢c放入缓冲轨中

	//为车厢c寻找最优缓冲轨
	int BestTrack=k;//初始化
	int BestTop=n+1; //最优缓冲轨的栈顶车厢编号

	int x;

	//扫描缓冲轨
	for(int i=0;i<k;i++)
	{
		if(!H[i].empty())
		{
			x=H[i].top();
			if(c<x && x<BestTop)
			{
				BestTop=x;
				BestTrack=i;
			}
		}
		else
		{
			//H[i]为空时
			if(BestTrack==k)
				BestTrack=i;
		}
	}

	if(BestTrack==k) //没有可用的缓冲轨
		return false;

	H[BestTrack].push(c);
	cout<<"Move car "<<c<<" from input to holding track "<<BestTrack+1<<endl;

	//必要时修改minH和minS
	if(c<minH)
	{
		minH=c;
		minS=BestTrack;
	}

	return true;
}
主函数

#include "mystack.h"

int main()
{
	int p[9]={3,6,9,2,4,7,1,8,5};
	if(Rail_Road(p,9,3))
		cout<<"车厢重排序成功"<<endl;
	else
		cout<<"车厢重排序失败"<<endl;
	return 0;
}

小结:多多做练习,做经典习题题目数,不能只停留在书本上,还要时间在代码上;