栈:一种只能从一端进出元素的具有先进后出性质的线性表。
队:一种只能在一端进另一端出的具有先进先出性质的线性表。
链栈与链队其储存方式是链式的。
回文数:从左读到右与从右读到左一样的正整数。如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");
}
由于要判断一个数是否为回文数,我把数字拆成一个个字符输入。
最后要强调的是链式线性表的空间问题,在出队或出栈时一定记得释放空间,否则会导致空间碎片(即存在这样的空间但不能被使用)的出现。
有问题、有想法,请留言讨论!