利用链栈与链队判断回文数

栈:一种只能从一端进出元素的具有先进后出性质的线性表。
队:一种只能在一端进另一端出的具有先进先出性质的线性表。
链栈与链队其储存方式是链式的。
回文数:从左读到右与从右读到左一样的正整数。如12321,112211,99。
利用队和栈来做这样的一个判断是非常容易理解的。
我们运用的就是他们各自的性质。
栈为先进后出 如输入 1 2 3 出3 2 1
队尾先进先出 如输入 1 2 3 出1 2 3
假若输入的是一个回文数 把该数分别入队入栈再输出 两个线性表的输出结果便是一样的。由此来判断一个数是否为回文数。
这里我只是单用队与栈来实现这么一个功能所以写的ADT(抽象数据类型)只是我所需要的

#pragma once//Stack.h 栈头文件
#include<stdio.h>
#include<malloc.h>
typedef  char elemtype;
typedef struct stack {
	elemtype date;
	struct stack* former;
}Stack,*PStack;

typedef struct 
{
	PStack top;
	PStack base;
	int lenth;
}linStack;

int Initstack(linStack *p)//初始化
{
	p->top = p->base = (PStack)malloc(sizeof(Stack));
	if (p->base == NULL)  return 0;
	p->lenth = 0;
	p->base->former = NULL;
	return 1;
}

void Destroy(linStack* p) //销毁
{
	while (p->top)
	{
		p->base = p->top->former;
		free(p->top);
		p->top = p->base;
   }
}

int Push(linStack* p, elemtype e) //入栈
{
	PStack q;
	q= (PStack)malloc(sizeof(Stack));
	if (q == NULL) return 0;
	q->former = p->top;
	p->top->date = e;
	p->top = q;
	p->lenth++;
	return 1;
}

int Pop(linStack* p, elemtype* e) //出栈
{
	Stack* q;
	if (p->base == p->top)
	{
	printf("栈为空!");
	return 0;
	}
		
	else
	{
		q = p->top->former;
		*e = q->date;
		free(p->top);
		p->top = q;
		p->lenth--;
	}
}

void PrintStack(linStack* p)  //全栈输出
{
	elemtype e;
	while (p->base != p->top)
	{
		Pop(p, &e);
		printf("%c->", e);
	}
}

我的栈节点是由date数据域和former指针域组成
这里为什么要用前指针呢,是因为栈的输出性质是由栈顶输出,
当栈顶项输出后便要循着指针往下走,所以得记录上一个元素的地址,从而队列由栈顶至栈底被连起来。

typedef struct stack {
	elemtype date;
	struct stack* former;
}Stack,*PStack;

另一个是储存栈顶与栈底地址的结构体
当你创建一个链栈的时候 栈就了有栈顶和栈底,这个结构体只储存这两个数据的地址,完事后的插入与删除只需要移动栈顶的位置就好了。

typedef struct 
{
	PStack top;
	PStack base;
	int lenth;
}linStack;

链式队列的构建其实和链式栈真的差不多,对比着看代码就明了了。

#pragma once//队头文件
#include<stdio.h>
#include<malloc.h>
typedef  char elemtype;
typedef struct Queue {
	elemtype date;
	struct Queue* next;
} Queue, *PQueue;

typedef struct {
	PQueue rear;
	PQueue front;
	int lenth;
}linQueue;

int InitQueue(linQueue* Q) //初始化队列
{
	Q->front = Q->rear = (PQueue)malloc(sizeof(Queue));
	if (Q->front == NULL) return 0;
	Q->rear->next = NULL;
	Q->lenth = 0;
}

void Destroy(linQueue* Q) //销毁队列
{
	while (Q->front)
	{
		Q->rear = Q->front->next;
		free(Q->front);
		Q->front = Q->rear;
	}
}

int InsertQueue(linQueue* Q,elemtype e) //入队
{
	 PQueue p;
	p= (PQueue)malloc(sizeof(Queue));
	if(p==NULL)return 0;
	p->date=e;
	p->next = NULL;
	Q->rear->next = p;
	Q->rear = p;
	Q->lenth++;
}

void DeQueue(linQueue* Q, elemtype* e)//出队
{
	PQueue p;
	if (Q->front->next)
	{
	p = Q->front->next;
			*e = p->date;
			free(Q->front);
			Q->front = p;
			Q->lenth--;
	}

	
}

void PrintQueue(linQueue* Q)//打印全队
{
	elemtype e;
	while (Q->front->next)
	{
		DeQueue(Q, &e);
		printf("%c->", e);
  }
	//printf("\n");
}

#include<stdio.h>
#include<Windows.h>
#include"Stack.h"
#include"Queue.h"

int Palinnum(linStack* p, linQueue*q)//输入与判断
{
	elemtype n=' ',e,e2;
	printf("please enter a string of number,let me judge palindormic number:");
	while (1)
	{
		scanf_s("%c",&n);
		if (n == '\n')break;  //不让换行进栈和队
        Push(p, n);
		InsertQueue(q,n);
	}
	while (p->lenth != 0)
	{
		Pop(p, &e); 
		DeQueue(q, &n); 
			
			if (e != n)
			{
				printf("你有没有搞错,它不回文数列!\n");
					return 1;
		}
	}
	printf("没错就是他了,回文数列!\n");
	return 0;
}

int main()
{
	int i = 3;
	elemtype n=0;
	linStack Sa;
	linQueue Qe;
	InitQueue(&Qe);
	Initstack(&Sa);
	Palinnum(&Sa,&Qe);
	system("pause");
}

由于要判断一个数是否为回文数,我把数字拆成一个个字符输入。
最后要强调的是链式线性表的空间问题,在出队或出栈时一定记得释放空间,否则会导致空间碎片(即存在这样的空间但不能被使用)的出现。
有问题、有想法,请留言讨论!

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值