数据结构算法之栈

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;
}

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

发布了26 篇原创文章 · 获赞 2 · 访问量 798

猜你喜欢

转载自blog.csdn.net/li_kin/article/details/103944595
今日推荐