链栈小解——举例进制转换

一个简单的链栈

#include<stdio.h>
typedef  struct  stacknode	      // 栈的存储结构
{  int data;                 // 定义数据类型 
  struct  stacknode  *next; // 定义一个结构体的链指针
} StackNode;

typedef  struct
{
  StackNode *top;
}LinkStack;//栈顶指针 

//初始化栈
void InitLinkStack(LinkStack &s)
{
	s.top=NULL;
}
//判栈空
int IsEmpty(LinkStack &s)
{
	if(NULL==s.top)
		return 1;
	else
		return 0;
}
//入栈
void Push(LinkStack &s,int x)
{
	StackNode *p=new StackNode;//申请新结点
	p->data=x;
	p->next=s.top;
	s.top=p;
}

//出栈
 int Pop(LinkStack &s,int &x)
{
	if(IsEmpty(s))
		return 0;
	else
	{
		StackNode *p=s.top;
		x=p->data;
		s.top=p->next;
		delete p;
		return 1;
	}
}

void ShowStack(LinkStack &s)
{
	if(IsEmpty(s))
		printf("栈为空!\n");
	else
	{
		StackNode *p=s.top;
		printf("栈元素为:");
		while(p!=NULL)
		{
			printf("%6d",p->data);
			p=p->next;
		}
		printf("\n");
    }
}

int main()
{
	LinkStack s;
	int x;
	 InitLinkStack(s);
	 Push(s,1);
	 Push(s,2);
	 Push(s,3);
	 ShowStack(s); 
	 Pop(s,x);
	 ShowStack(s); 	
} 

对于链栈,和顺序栈最大的不同就是没有大小限制。然后在输出的时候,你要一个一个的遍历,同时delete这个节点,释放空间。
再看看进制转换的程序例子,当你在写他的时候,你会遇到一个很诡异的问题,当时我这个问题想了半天才整明白逻辑。

#include <iostream>
#include <stdio.h>

typedef struct LinkNode{
	int data;
	struct LinkNode *next;
}linknode;

typedef struct LinkStack{
	LinkNode *top;
}linkstack;

//初始化
void CreateLink(linkstack &head){
	head.top=NULL;	
} 

//判栈空
bool IsEmpty(linkstack &head)
{
	if(NULL==head.top)
		return true;
	else
		return false;
}

//------------------------------------------------------我是功能块分割线------------------------------------------------------// 

//出栈 
void OutStack(linkstack &head){
	if(IsEmpty(head)){
		printf("栈里面啥都没有!!\n");
	} else {
		linknode *p;
		int z=1;
		while(z){
			p=head.top;
			printf("%d ",p->data);
			if(p->next){
				head.top=p->next;
				delete p;
			} else {
				z=0;
			}
		}
	}
} 

//进栈
void InStack(linkstack &head,int num){
	linknode *p=new linknode;
	p->data=num;
	p->next=head.top;
	head.top=p;
} 

 //------------------------------------------------------我是功能块分割线------------------------------------------------------// 

//转二功能 
 void TWO(linkstack &head,int tenNum){
	int num1;
	while(1){
		num1=tenNum%2;
		InStack(head,num1);
		tenNum/=2;
		if(tenNum == 1){
			InStack(head,tenNum);
			break;
		}
	}
	printf("该数的二进制形式:");
	OutStack(head);
 }
 
//转二
 void ChangeTwo(){
 	linkstack head;
 	CreateLink(head);
 	int tenNum;
 	printf("请输入十进制数:");
 	scanf("%d",&tenNum);
 	TWO(head,tenNum);
 } 

 //------------------------------------------------------我是功能块分割线------------------------------------------------------// 

//转八功能
 void EIGHT(linkstack &head,int eightNum){
	int num1;
	while(1){
		num1=eightNum%8;
		InStack(head,num1);
		eightNum/=8;
		if(eightNum <= 7 && eightNum>0){
			InStack(head,eightNum);
			break;
		}
		if(eightNum == 0){
			break;
		}
	}
	printf("该数的八进制形式:");
	OutStack(head);
 }
 
//转八
 void  ChangeEight(){
 	linkstack head;
 	CreateLink(head);
 	int eightNum;
 	printf("请输入十进制数:");
 	scanf("%d",&eightNum);
 	EIGHT(head,eightNum);
 }
 
 //------------------------------------------------------我是功能块分割线------------------------------------------------------// 

 //转十六功能
 void SIXTEEN(linkstack &head,int sixteenNum){
	int num1;
	while(1){
		num1=sixteenNum%16;
		InStack(head,num1);
		sixteenNum/=16;
		if(sixteenNum <= 15 && sixteenNum>0){
			InStack(head,sixteenNum);
			break;
		} 
		if(sixteenNum == 0){
			break;
		}
	}
	
 	int i=0;
 	linknode *p;
 	printf("该数的十六进制形式:");
	while(1){
		p=head.top;
		
		//数值在9以下,包括九,不用转换成字符 
 		if(p->data >=0 && p->data <=9){
 			printf("%d",p->data);
 		} 
		 else if(p->data >= 10 && p->data <= 15){   //数值在十以上,十五以下,包括十和十五,要转换成对应的字符
 			switch(p->data){
 				case 10:
 					printf(" a ");
 					break;
 				case 11:
 					printf(" b ");
 					break;
 				case 12:
 					printf(" c ");
 					break;
 				case 13:
 					printf(" d ");
 					break;
 				case 14:
 					printf(" e ");
 					break;
 				case 15:
 					printf(" f ");
 					break;
			 }
		 }
		 
		 head.top=p->next;
		 delete p;
	}
	
	
 }
 //转十六 
 void ChangeSixteen(){
 	linkstack head;
 	CreateLink(head);
 	int sixteenNum;
 	printf("请输入十进制数:");
 	printf("(温馨提示:该十六进制功能大小)\n");
 	scanf("%d",&sixteenNum);
 	SIXTEEN(head,sixteenNum);
 }
 
 //------------------------------------------------------我是功能块分割线------------------------------------------------------// 

//菜单
void menu(){
	printf("\n~~~~~~1、十转二 2、十转八~~~~~~\n");
	printf("\n~~~~~~3、十转十六 4、退出~~~~~~\n");
	
}
int main(){
	int z=1;
	int choose;
	printf("请根据菜单选择功能,输入对应的序号!!!\n");
	while(z){
		menu();
		printf("输入序号:");
		scanf("%d",&choose);
		switch(choose){
			case 1: 
				ChangeTwo();break;
			case 2:
				ChangeEight();break;
			case 3:
				ChangeSixteen();break;
			case 4:
				exit(0);
			default:
				printf("输入错误!!");
		} 
	}
}

对于进制转换,大家都没问题,就是不断的模进制,然后直到最后一个数小于进制数。但是,你的进制转换完了,他要从下往上读,即你最先模出来的数是各位上的数。
转头一想,这不就是栈吗!?!最先模出来的数压入栈底,然后释放的时候就成了最后一个数。
但是大小呢,你的顺序栈是有大小限制的,你要是整个超级大,这会浪费存储空间资源,你要是整小了,又不够用。
所以链栈这种无限大小的、你用多少就创建多少空间的栈就非常实用了。
但是,又有一个新的问题,上面提过,如果按照以前的链式结构来写,在你输出的时候会有问题。
首先你要获取你的链式末尾的值,充当第一个输出的头值,即先进后出、后进先出。
这个有办法解决。我们专门建立一个结构体指针,专门指向链式最末尾的值,这样我就不用再遍历到链栈的末尾,来获取第一个输出的值。
但是新的问题又来了。比如你的链栈是4321,你得到了1,并输出了1,2呢、3呢、4呢,你如何获取。
如果按照以前的链式结构来写,你的每个节点的指针域是指向下一个节点的,即你可以从4获取3的地址,葱获取2的地址,以此类推。可你没法反向获取地址。
不知道看过我别的文章的读者是否还记得,我有篇文章讲过,链的头结点-尾插法,对应我们是不是还有头结点-头插法?
这个是可以有的。我们建立一个结点a1,并用一个空闲的该结构体类型的指针 p 绑定他的地址,当来了个新的结点a2,我们用p的指针域获取a2的地址,然后再将p绑定a1,这样就完成了。而p就可以是那个一直指向顶层结点的结构体指针。
是不是很简单,但是有些绕呢??
慢慢理解来着吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值