数据结构(C++) 2-1 栈的简单应用(回文数)

题目描述
我们把从左往右和从右往左念起来相同的数字叫做回文数。
某个数用某个进制表示不是回文数,但是用别的进制表示可能就是回文数。
例如,17是用十进制表示的数,显然它不是一个回文数,但是将17用二进制表示出来是10001。
现在给一个用十进制表示的数,请判断它在2~16进制下是否是回文数。
输入
输入包含多组测试数据。每组输入一个用十进制表示的正整数n(0 < n< 50000),当n=0时结束。
输出
对于每组输入,如果n在2~16进制中的某些进制表示下是回文数,则输出“Number i is palindrom in basis ”,在后面接着输出那些进制。其中i用n的值代替,后面输出的进制中,每两个数字之间空一个。
如果n在2~16进制的表示下都不为回文数,则输出“Number i is not a palindrom”,其中i用n的值代替。
想法是:
在转换进制的时候由于要反序,所以用栈来实现,在判断回文数的时候也是用栈来实现(我也觉得挺鸡肋的。。。)
注意:
若转换进制之后若只有个位数有值,那么它也为回文数。
关键处有注释
代码如下:

#include<iostream>
using namespace std;
struct Node
{
	int data;
	Node* link;
	Node()
	{
		data = 0;
		link = NULL;
	}
	Node(int d)
	{
		data = d;
		link = NULL;
	}
};
class LinkStack
{
public:
	Node* first;  //头结点存储输入判断的数据,其余结点存储权位的值
	Node* Locate(int i);  //定位,返回地址,仅仅是给公有成员用
//public:
	LinkStack();  //构造函数
	LinkStack(int num);  //构造函数
	int Lenth();  //计算长度
	int GetNum() { return first->data; }
	void Push(int num);  //压栈
	void Clear();  //清空栈
	int Pop();  //弹出
};

LinkStack::LinkStack()
{
	first = new Node;
}
LinkStack::LinkStack(int num)
{
	first = new Node(num);
}

int LinkStack::Lenth()
{
	Node* current = first;
	int count = 0;
	while (current->link != NULL)
	{
		current = current->link;
		count++;
	}
	return count;
}

Node* LinkStack::Locate(int i)
{
	int count = 0;
	Node* current = first;
	for (count; count < i; count++)
	{
		current = current->link;
	}
	return current;
}

void LinkStack::Push(int num)
{
	int x = this->Lenth();
	Node* current = this->Locate(x);
	Node* newnode = new Node(num);
	if (newnode == NULL)
	{
		cerr << "error !" << endl;
		exit(1);
	}
	current->link = newnode;
}

void LinkStack::Clear()
{
	int len = this->Lenth();
	for (int i = 0; i < len; i++)
	{
		this->Pop();
	}
	first->link = NULL;
}
int LinkStack::Pop()
{
	int x = this->Lenth() - 1;  //定位到栈顶前一个
	Node* current = this->Locate(x);
	int value = current->link->data;
	delete current->link;
	current->link = NULL;
	return value;
}
void radix(LinkStack& a, int m)  //转换进制
{
	int num1 = a.GetNum();
	if (num1 < m)
	{
		a.Push(num1);
		return;  //如果数小于进制,则只有个位有数值,单个的也为回文数,直接返回主函数
	}
	int x;  //记录余数
	do   //由于进制转换的时候要反序,所以考虑压栈
	{
		x = num1 % m;
		num1 = num1 / m;
		a.Push(x);  //进制压栈
	} while (num1 / m);
	a.Push(num1);
}

bool judge(LinkStack& a)  //judge whether it is palindrome
{
	LinkStack b;  //回文数判断时需要压栈,所以新建一个栈
	int x = a.Lenth() % 2;  //需要判断长度的奇偶
	int temp1 = a.Lenth() / 2;  //防止循环进行的时候lenth一直改变
	for (int i = 0; i < temp1; i++)
	{
		b.Push(a.Pop());  //将转换为进制的一半压到b栈,并且弹出a栈的一半
	}
	if (x==1)  //为奇数
	{
		int y = a.Pop();  //去掉a栈里面原来中间的元素(现在栈顶的元素)
	}
	int temp = a.Lenth();  //用temp代替,
	for (int i = 0; i < temp; i++)
	{
		int x = a.Pop(); 
		int y = b.Pop();
		if (x!=y) return false;  //判断回文
	}
	return true;
}

int main()
{
	while (1)
	{
		int num;  //判断的数据
		int count = 0;  //用于计数
		int x[50];  //用于记录是回文数的进制
		cin >> num;
		if (num == 0) break;
		LinkStack a(num);
		for (int i = 2; i < 17; i++)  //判断各种进制的可能,并将是回文数的进制记入数组
		{
			radix(a, i);
			if (judge(a))
			{
				x[count] = i;
				count++;
			}
			a.Clear();
		}
		if (count == 0)
		{
			cout << "Number " << a.GetNum() << " is not a palindrom" << endl;
		}
		else
		{
			cout << "Number " << a.GetNum() << " is palindrom in basis ";
			for (int i = 0; i < count; i++)
			{
				cout << x[i] << ' ';
			}
			cout << endl;
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值