实验要求
(1)能够用高级语言描述栈的存储结构;
(2)能够用高级语言编写栈的入栈和出栈等基本操作算法并通过程序测试其正确性;
(3)能够运用栈的基本操作解决简单的实际应用问题。
实验目的
编程实现建立一个数据元素值是一个字符的单链表,并借助栈的入栈、出栈等操作判断此单链表中字符序列是否构成回文的操作。
分析
通过一个栈就可以实现,将链表元素全部入栈后,根据栈的特性,后进先出原则,先pop的元素是链表的队尾元素,所以只要通过pop将元素与链表首元素逐一比较即可。
代码段
下面展示代码片段。
#include<stdio.h>
#include<stdlib.h>
#include <malloc.h>
#define ERROR 0
#define OK 1
#define OVERFLOW -1
#define STACK_INIT_SIZE 100 //顺序栈的预分配的空间大小
#define STACKINCREMENT 20
typedef char SElemType;
typedef int Status;
typedef struct {
SElemType *base; // 栈的存储空间基地址(栈底指针)
SElemType *top ; //指示栈顶元素的下一存储单元的位置(栈顶指针)
int stacksize; //栈当前的存储空间容量
}SqStack;
Status InitStack( SqStack &S)
// 创建一个空的顺序栈 S
{
S.base=(SElemType*) malloc (STACK_INIT_SIZE*sizeof (SElemType)); // 分配预定义大小的存储空间
if (!S.base) //如果空间分配失败
exit(OVERFLOW);
S.top= S.base; //置当前栈顶指针指向栈底的位置
S.stacksize =STACK_INIT_SIZE; //置当前分配的存储空间容量为 STACK_INIT_SIZE 的值
return OK;
}
Status Push(SqStack &S, SElemType e)// 在顺序栈 S 中插入新的元素 e, 使其成为新的栈顶元素
{ if (S.top-S.base>= S.stacksize) //当前存储空间已满,则扩充空间
{S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if (!S.base) //如果空间分配失败
exit(OVERFLOW);
S.top = S.base+S.stacksize; //修改增加空间后的基址
S.stacksize += STACKINCREMENT; //修改增加空间后的存储空间容量
}
*S.top++=e; //e 压栈后,top 指针再后移一位
return OK;
}
char Pop(SqStack &S, SElemType &e)// **删除顺序栈 S 中的栈顶数据元素,并用 e 返回其值**
{ if (S.base==S.top) //如果栈空
{ printf("The Stack is NULL!\n");
return ERROR;
}
e=*--S.top; //删除栈顶元素并用 e 返回其值
return e;
}
void Out(SqStack S) //顺序栈的输出函数
{ SElemType *p;
for(p=S.base; p<S.top;p++) //依次输出栈中各元素的值,栈顶元素在表的尾部
printf("%c", *p);
printf("\n");
}
struct node//定义结点结构体
{
char ch;
struct node *next;
};
typedef struct node Node;//重命名 结点结构体变量
typedef struct node* Link;//重命名 指向结点结构体的指针变量
int strlen_s(char *s)//求字符串长度
{
int i = 0;
while (*s != '\n')
{
i++;
s++;
}
return i;
}
void create_link(Link *head)//创建链表,
{
*head = NULL;//空链表
}
void is_malloc_ok(Link new_node)//判断新结点是否分配空间成功
{
if (NULL == new_node)
{
printf("malloc error!\n");
exit(-1);
}
}
void create_new_node(Link *new_node)//创建新结点
{
*new_node = (Link)malloc(sizeof(Node));
is_malloc_ok(*new_node);
}
void insert_tail(Link *head, Link new_node)//尾插新结点
{
Link tmp;
tmp = *head;
if (NULL == *head)//空链表,只能头插
{
new_node->next = *head;
*head = new_node;
}
else
{
while (tmp->next != NULL)//找到尾结点
{
tmp = tmp->next;
}
tmp->next = new_node;
new_node->next = NULL;
}
}
void display_link(Link head)//串的内容
{
Link tmp;
tmp = head;
if (NULL == head)//空链表
{
printf("Link is empty!\n");
return ;
}
printf("串链表为:\n");
while (tmp != NULL)
{
printf("%c",tmp->ch);
tmp = tmp->next;
}
}
void pushhead(Link head,SqStack &S)//将链表里面的元素压入栈中
{
Link tmp;
tmp = head;
if (NULL == head)//空链表
{
printf("Link is empty!\n");
return ;
}
printf("\n压入栈中的元素为:\n");
while (tmp != NULL)
{
Push(S,tmp->ch); //将链表元素入栈
tmp = tmp->next;
}
Out(S);
}
void ishuiwen(Link head,SqStack S) //**判断回文函数**
{
Link tmp;
tmp = head;
char e;
int flag=1;
while (tmp != NULL)
{
e=Pop(S,e); //用e取出栈顶元素
if(tmp->ch!=e){ //栈顶元素与链表首元素比较
flag=0;}
tmp = tmp->next;
}
if(flag==0)
printf("此链表中的字符序列不构成回文");
else
printf("此链表中的字符序列构成回文");
}
int main()
{
Link head = NULL;
Link new_node = NULL;
int i;
int len;
char s[20];
SqStack S;
InitStack(S);
printf("输入不超过20个字符:\n");
fgets(s,20,stdin);//输入流
len = strlen_s(s);
create_link(&head);//创建链表
for (i = 0; i < len; i++)
{
create_new_node(&new_node);//创建新结点
new_node->ch = s[i];//为新结点成员赋值
insert_tail(&head, new_node);//尾插新结点
}
display_link(head);//显示链表元素
pushhead(head,S);//将链表元素逐个压入栈中
ishuiwen(head,S);//判断栈元素与链表元素逆向比较判断回文
return 0;
}
结果