1. 程式人生 > >鏈棧的建立與使用,進位制轉換與括號匹配問題

鏈棧的建立與使用,進位制轉換與括號匹配問題

鏈棧的建立與使用(先進後出)     包含兩個運用                 1.判斷一個表示式中符號"(",")","[","]","{","}"是否匹配,若匹配返回1,不匹配返回0;                 2.數制轉換:將十進位制轉換為隨意進位制

問題:         1.中途卡在了遍歷棧和出棧函式上,想遍歷來看看是否存進了資料           除錯了幾次,都是在賦值給x和輸出附近出現問題,多次蹦出CPU視窗,判斷是記憶體和存值問題,初次改動沒有成功,反而無法輸入,進入函式後沒有執行,直接結束程式,附圖

        2.懷疑是賦值問題,可能需要記憶體??         後來查詢了他人的程式碼,發現大多數定義棧頂指標都喜歡用結構體並附帶棧的長度         自己試了一下並沒有太大改善,反而輸出出現了問題         後來想用和他們一樣,定義棧頂指標結構體然後定義結構體指標,雙重指標進行建表輸出,但沒有實行,         感覺應該有更方便的方法。         附帶程式碼連線:          

https://blog.csdn.net/HZPHYT/article/details/81369022           https://www.cnblogs.com/yudongxuan/p/7728195.html                  3.後來先去寫了佇列,發現瞭解決辦法,給棧頂指標分配記憶體,並且在主函式內分配空間,然後將next=NULL         嘗試過分配記憶體以後給ls直接賦值NULL,但輸出出了問題,後來仍然使用next。輸出問題附圖:

        4.整形轉換為字元型                (1) char c;                            (2)char c;                 int a;                               int a;                 c=a+48;                            c=a+'0';

 

程式一:括號匹配

//括號匹配結構體 
typedef struct stnode
{
	char data;
	struct stnode *next;
	
}LinkStack; 

將記憶體分配放在了主函式內,放在初始化函式內無法正常執行,費了很多時間才弄好

//棧的初始化操作 
void InitStack(LinkStack *ls)
{
	ls->next=NULL;
}

入棧操作。費了半天勁才調好

//符號入棧操作 
void Push(LinkStack *ls,char x)
{
	LinkStack *p;                                    
	p=(LinkStack*)malloc(sizeof(LinkStack));
	p->data=x;										                                         
	p->next=ls->next;//->next;							
	ls->next=p;								//先使p->next指向ls(即ls此時對應的結點),然後改變ls指向
														
}

出棧操作

//符號出棧 
void Pop(LinkStack *ls)
{
	LinkStack *p;
	p=ls->next;
	ls->next=ls->next->next;
	free(p);
} 

為了在寫的時候觀察是否建立成功寫的遍歷函式

//遍歷棧中元素 
 
int ShowStack(LinkStack *ls)
{
	LinkStack *p;
	p=ls->next;
	if(p==NULL)
			{
				printf("為空棧\n");
				return 0;
			}		
	while(p!=NULL)													//ls=p->next;
	{
		printf("元素為:%c\n",p->data);
		p=p->next;
		
	}
	return 0;
}	

重點函式,匹配,返回值是為了中途不匹配返回0,直接跳出

//符號匹配函式
int Exps(LinkStack *ls,char x)
{
	switch(x)
	{
		case '(':Push(ls,x);break;                          //輸入符號並進行壓棧操作
		case '{':Push(ls,x);break;                          //輸入符號並進行壓棧操作
		case '[':Push(ls,x);break;                          //輸入符號並進行壓棧操作
		case ')':											//進行匹配,若匹配,則出棧一個,不匹配則進棧 
			if(ls->next->data=='(')
			{
				Pop(ls);
				break;
			}
			else
			{
				printf("不匹配\n"); 					          //若不匹配,則返回選單 
				return 0;
			}
		case '}':											//進行匹配,若匹配,則出棧一個,不匹配則進棧 
			if(ls->next->data=='{')
			{
				Pop(ls);
				break;
			}
			else
			{
				printf("不匹配\n"); 					          //若不匹配,則返回選單 
				return 0;
			}
		case ']':											//進行匹配,若匹配,則出棧一個,不匹配則進棧 
			if(ls->next->data=='[')
			{
				Pop(ls);
				break;
			}
			else
			{
				printf("不匹配\n"); 					          //若不匹配,則返回選單 
				return 0;
			}
	}
	return 1; 

程式二:進位制轉換函式

結構體和初始化一起寫了

typedef struct stmath
{
	char num;
	struct stmath *rear;
	
}LinkMath; 
//進位制轉化初始化 
void Math_Stack(LinkMath *lq)
{
	lq->rear=NULL;
}

進位制入棧和轉換函式

//進位制入棧
void Push_Math(LinkMath *lq,char y)
{
	LinkMath *s;
	s=(LinkMath*)malloc(sizeof(LinkMath));
	s->num=y;							//存入連結串列,以便倒敘 
	s->rear=lq->rear;
	lq->rear=s; 
} 

//進位制轉換函式
void ZhuanStack(LinkMath *lq,int num1,int j)
{
	int z;                        //定義整形用於計算 
	char y;						  //字元型用來存餘數並轉換為字元型 
	LinkMath *t;
	while(num1!=0)				  //num1不為0,則繼續 
	{
		z=num1%j;				//取餘數 
		if(z>10)				//餘數大於10,則轉換進位制大於10,需要字母 
		{
			y='A'+z%10;			//計算相應字母 
		}
		else
		{
			y=z+'0';			//轉換進位制不大於10或餘數不大於10,無需字母,轉換為字元型 
		}
		num1=num1/j;			//num1取整 
		Push_Math(lq,y);        //進位制入棧函式 
	}
	t=lq->rear; 
	while(t!=NULL)
	{
		printf("%c",t->num);   //對進位制棧進行遍歷輸出 
		t=t->rear;
	}
	printf("\n");
} 

程式中都用個人認為比較詳細的註釋,就不詳細講解了

附圖完整程式碼

#include <stdio.h>
#include <stdlib.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */



//括號匹配結構體 
typedef struct stnode
{
	char data;
	struct stnode *next;
	
}LinkStack; 

//進位制轉換結構體 
typedef struct stmath
{
	char num;
	struct stmath *rear;
	
}LinkMath; 


//棧的初始化操作 
void InitStack(LinkStack *ls)
{
	ls->next=NULL;
}

//進位制轉化初始化 
void Math_Stack(LinkMath *lq)
{
	lq->rear=NULL;
}

//符號入棧操作 
void Push(LinkStack *ls,char x)
{
	LinkStack *p;                                    
	p=(LinkStack*)malloc(sizeof(LinkStack));
	p->data=x;										                                         
	p->next=ls->next;//->next;							
	ls->next=p;								//先使p->next指向ls(即ls此時對應的結點),然後改變ls指向
														
}

//進位制入棧
void Push_Math(LinkMath *lq,char y)
{
	LinkMath *s;
	s=(LinkMath*)malloc(sizeof(LinkMath));
	s->num=y;							//存入連結串列,以便倒敘 
	s->rear=lq->rear;
	lq->rear=s; 
} 

//符號出棧 
void Pop(LinkStack *ls)
{
	LinkStack *p;
	p=ls->next;
	ls->next=ls->next->next;
	free(p);
} 

//遍歷棧中元素 
 
int ShowStack(LinkStack *ls)
{
	LinkStack *p;
	p=ls->next;
	if(p==NULL)
			{
				printf("為空棧\n");
				return 0;
			}		
	while(p!=NULL)													//ls=p->next;
	{
		printf("元素為:%c\n",p->data);
		p=p->next;
		
	}
	return 0;
}	
 

//符號匹配函式
int Exps(LinkStack *ls,char x)
{
	switch(x)
	{
		case '(':Push(ls,x);break;                          //輸入符號並進行壓棧操作
		case '{':Push(ls,x);break;                          //輸入符號並進行壓棧操作
		case '[':Push(ls,x);break;                          //輸入符號並進行壓棧操作
		case ')':											//進行匹配,若匹配,則出棧一個,不匹配則進棧 
			if(ls->next->data=='(')
			{
				Pop(ls);
				break;
			}
			else
			{
				printf("不匹配\n"); 					          //若不匹配,則返回選單 
				return 0;
			}
		case '}':											//進行匹配,若匹配,則出棧一個,不匹配則進棧 
			if(ls->next->data=='{')
			{
				Pop(ls);
				break;
			}
			else
			{
				printf("不匹配\n"); 					          //若不匹配,則返回選單 
				return 0;
			}
		case ']':											//進行匹配,若匹配,則出棧一個,不匹配則進棧 
			if(ls->next->data=='[')
			{
				Pop(ls);
				break;
			}
			else
			{
				printf("不匹配\n"); 					          //若不匹配,則返回選單 
				return 0;
			}
	}
	return 1; 
} 

//進位制轉換函式
void ZhuanStack(LinkMath *lq,int num1,int j)
{
	int z;                        //定義整形用於計算 
	char y;						  //字元型用來存餘數並轉換為字元型 
	LinkMath *t;
	while(num1!=0)				  //num1不為0,則繼續 
	{
		z=num1%j;				//取餘數 
		if(z>10)				//餘數大於10,則轉換進位制大於10,需要字母 
		{
			y='A'+z%10;			//計算相應字母 
		}
		else
		{
			y=z+'0';			//轉換進位制不大於10或餘數不大於10,無需字母,轉換為字元型 
		}
		num1=num1/j;			//num1取整 
		Push_Math(lq,y);        //進位制入棧函式 
	}
	t=lq->rear; 
	while(t!=NULL)
	{
		printf("%c",t->num);   //對進位制棧進行遍歷輸出 
		t=t->rear;
	}
	printf("\n");
} 
												
int main() 
{
	char x;						//輸入括號 
	int i;						//判斷返回值以確定匹配 
	LinkStack *ls;				//括號棧頂指標 
	LinkMath *lq;				//進位制棧頂指標 
	int num1,j;					//轉換的數值以及轉換成的進位制 
	ls=(LinkStack*)malloc(sizeof(LinkStack));
	lq=(LinkMath*)malloc(sizeof(LinkMath));
	Math_Stack(lq); 
	InitStack(ls); 						//對棧進行初始化                                     
	while(1)
	{
		printf("---------------1.括號匹配--------------\n");
		printf("---------------2.進位制轉換--------------\n");
		printf("---------------3.遍歷元素--------------\n");
		printf("請選擇功能:");
		scanf("%d",&i);
		scanf("%c",&x);						//多餘的輸入,用來存入輸入選擇以後再次輸入的回車'\n',排除'\n'影響 
		switch(i)
		{
			case 1:
				printf("請輸入括號:");
				while(1)                                 	   
				{
					scanf("%c",&x);
					if(x=='\n')						//當x==回車鍵時停止輸入,並判斷是否為空,為空則全部匹配 
					{
						if(ls->next==NULL)
						{
							printf("括號匹配\n");
							break;
						}
						else
						{
							printf("括號不匹配\n");
							break;
						}
							 
					}	
					i=Exps(ls,x);					//進入符號匹配函式
					if(i==0)						//如果匹配中途不匹配,則返回0,並退出迴圈 
						break; 
				//	Push(ls,x);                     //輸入符號並進行壓棧操作
						 
				}
				break;
			case 2:
				printf("請輸入數字:");
				scanf("%d",&num1);
				printf("請輸入進位制:");
				scanf("%d",&j);
				ZhuanStack(lq,num1,j);
				break; 
			case 3:
				ShowStack(ls);
				break; 
				
				
		}
	} 
	
	
	return 0;
}

如有錯誤,請及時指出,謝謝