栈和队列时操作受限制的线性表。
正是因为它们都是受限制的,所以采用顺序存储结构比较方便,因为顺序存储结构与链式存储结构的比较是,插入/删除操作比较不方便,需要移动元素,而此两种数据结构正好限制了插入删除操作。所以就使用顺序存储结构比较合理。
栈 ( 十分有用的数据结构, 递归调用 等等 )
栈 : 限制在表尾进行插入删除操作 ( 入栈 出栈 , 后进先出 )
队列 : ( 先进先出 , 如同现实的队列 )
顺序栈 : 用一组地址连续的空间,存储。(常用 )
先为栈分配一个基本容量,然后在应用过程中,当栈的空间不够使用时再逐段扩大。
push : top 向上,top + 1
pop : top 向下,top - 1
定义 : typedef struct {
ElemType *base ; //栈底指针
ElemType *top ; //栈顶指针
int stacksize ; //栈的被分配空间
}SqStack ;
空栈 : base = top
借助高级语言数组 定义 :typedef struct {
int data[ STACKSIZE ] ; // stacksize 之前 #define
int base ; // 栈底 ( 用元素的坐标表示 )
int top ; // 栈顶
}SqStack ;
个人认为借助高级语言实现
typedef struct {
ELEM_TYPE data[STACKSIZE];
int top;
} sqstack;
因为 0 就是栈底, 不用再另外定义栈底
这个是对的
递归函数调用 用到栈 , 递归工作栈 , 可以自己用栈实现递归( 后续还有补充 )难点
通常,在一个函数的运行期间调用另一个函数时,在运行被调用函数之前,系统需要完成3件事:
1。将所有的实在参数,返回地址等信息传递给被调用函数保存。
2。为被调用函数的局部变量分配存储区
3。将控制转移到被调函数入口。
从被调函数返回:
1。保存被调函数的计算结果
2。释放被调函数数据区
3。依照被调函数的返回地址将控制转移到调用函数
由于多个函数嵌套调用时,按照“后调用先返回”的原则。用栈实现。
栈的应用举例很多。 ( 看下边例子,程序补充 )
链栈 :很少使用,详细请基本参考链表。
很少使用的原因,个人觉得:由于链式结构之间的逻辑关系时依靠指针连接 *next ,特点是插入和删除操作时,不需要移动其他单元。
由于栈规定了插入删除操作( 入栈 出栈 ) 只能在表尾(栈顶) 如果选择顺序结构也不涉及到元素一定( 入栈 出栈 时) , 所以选择顺序栈比较合适。
而如果使用链栈则不仅要保存*next信息,还要保存 *base , *top 信息。
综上,选择数据结构要根据操作的方便性。
链栈的栈顶指针 应该是 链栈的首地址 ( 反着 )
栈顶指针 -> 结点1 -> 结点2 -> 结点3 ......
如下图 : 分析链栈存储结构
状态1 : top指针于base指针都是指向栈底,刚刚分配栈空间。
状态2 : 栈内存储数据,此时base指针不变,top指针增加,注意当再新增加数据时,只是找top指针,然后增加数据,并修改top指针。
状态3 : 出栈,首先可以找到top指针出栈,但是栈顶指针此时需要变更,无法找到它之前的元素,因为next指针只是向后,除非使用双链表。
所以使用链栈时,出栈会有一点小麻烦。
队列 ( 跟栈相反 先进先出 ) ( 基本上都是循环队列,因为空间需要反复利用啊,要不就越来越浪费空间 )
只准许在表的一端插入,而在另一个端删除。( 现实一致,删除的一端叫队头,出队 , 插入的一端叫队尾, 入队 )
顺序队列 定义 :定义 : typedef struct { 基本上是循环队列(我们所说的顺序队列就是循环队列)
ElemType *elem //存储单元
ElemType *front ; //队头指针
ElemType *rear ; //队尾指针
int queuesize ; //队列的被分配空间
}SqQueue ;
借助高级语言数组 实现 :typedef struct {
int data[ SEQSIZE ] ; // seqsize 之前 #define
int front ; // 队头 ( 用元素的坐标表示 )
int rear ; // 队尾
}SqQueue ;
如上图 : 队列前端已经空了,但是此队列的状态时满的( 在想从 rear 插入数据已经不行了) 因此引入 循环队列
因为不能通过 front = rear 判断队“满“ 或者 队”空“ ,则浪费一个存储空间,将 ( rear + 1 ) % 存储空间 = front , 则判断为对满
关键看谁追上谁,如果是 front 追上 rear , 空队列,如果是 rear 追上了 front 就是满队列.
所以 一般的顺序队列叫做循环队列。
QElemType elem ; //存储单元
struct QNode *next ; //指针
} QNode , *QueuePtr ; // 结点定义
typedef struct {
QueuePtr front ; //队头指针
QueuePtr rear ; //队尾指针
} * LinkQueue ;
链队列同链表一样,也有头结点。
空队列 : front指针指向头结点 , rear指针指向头结点。
出入队列 : 从front指针出,从rear指针入。
出列时要修改头结点的next指针,而不时front所指向的头结点。( 当链队列中只有一个元素时,即出队列就变成空队列,此时不仅仅要修改头结点
的next指针,同时要修改 rear指针,指向头结点,因为此时已经时空队列 )
入队列时要修改 a3->next指针,指向新插入的元素并且要修改rear指针指向新插入的元素。
补充 : 表达式表示与求值 ( 详细参考 getchar & 表达式求值 )
1. a( 练习册 3.10 递归实现 )
/* Use the recursion practic 3.10
** Author : kevin
** Date : 2012/02/24
*/
#include"stdio.h"
void test( int sum )
{
int x;
scanf("%d",&x);
if(x==0){
sum = 0;
}
else{
test(sum);
sum += x ;
}
printf("%d,",sum);
}
int main()
{
test(5);
getchar();
getchar();
}
1. b( 练习册 3.10 栈实现 )
/* Modify the recursion to stack practic 3.10
** Author : kevin
** Date : 2012/02/24
*/
#include"stdio.h"
#include"stdlib.h"
#include"alloc.h"
typedef struct {
int data[50]; /*store data*/
int base ; /*base*/
int top ; /*top*/
}SqStack ;
void InitStack( SqStack *ps)
{
int i ;
for(i=0; i<50; i++){
ps->data[i] = 0;
}
ps->base = 0 ;
ps->top = 0 ;
}
void PushStack( SqStack *ps , int e )
{
int n ;
n = ps->top ;
ps->data[n] = e ;
ps->top++;
}
int PopStack( SqStack *ps )
{
int n ,e ;
n = ps->top -1;
e = ps->data[n] ;
ps->top--;
return e ;
}
int main()
{
int x ;
int sum ;
int i ;
int result ;
SqStack sq ;
InitStack( &sq);
printf("Please input the sum value \n");
scanf("%d",&sum);
printf("\nPlease input the x value\n");
scanf("%d",&x);
for(;x!=0;){
PushStack(&sq,x);
scanf("%d",&x);
}
if(x==0){
printf("%d,",x);
}
for(i=sq.top-1;i>=0;i--){
result = PopStack(&sq);
sum = 5;
sum += result ;
printf("%d,",sum);
}
getchar();
getchar();
}/*Caution:This program value(sum),you can push the sum value into stack too , and that is the better*/
2.( 练习册 3.15 )
/* double direction stack , practice 3.15
** Author : kevin
** Date : 2012/02/24
*/
#include"stdio.h"
#include"stdlib.h"
#include"alloc.h"
/*The define of stack*/
typedef struct {
int data[50]; /*Save data , 50 is stack size*/
int baseLeft ; /*stack's left base*/
int topLeft ; /*stack's left top*/
int baseRight ; /*stack's right base*/
int topRight ; /*stack's right top*/
}SqStack ;
/*Init stack*/
void InitStack( SqStack *ps )
{
int i ;
for(i=0; i<50; i++){
ps->data[i] = 0;
}
ps->baseLeft = 0 ;
ps->topLeft = 0 ;
ps->baseRight = 49;
ps->topRight = 49 ;
}
/*Push stack*/
void PushStack( SqStack *ps , int i , int e)
{
int n ;
if(i==1){
n = ps->topLeft;
ps->data[n] = e ;
ps->topLeft++ ;
}else{
n = ps->topRight;
ps->data[n] = e ;
ps->topRight-- ;
}
}
/*Pop stack*/
int PopStack( SqStack *ps , int i )
{
int n , e ;
if(i==1){
n = ps->topLeft;
e = ps->data[n];
ps->topLeft-- ;
return(e);
}else{
n = ps->topRight;
e = ps->data[n];
ps->topRight++ ;
return(e);
}
}
/*Display*/
void DisplayStack(SqStack *ps)
{
int i ;
printf("The first stack is \n");
for(i=0;itopLeft;i++)
printf("%d,",ps->data[i]);
printf("\n");
printf("The second stack is \n");
for(i=49;i>ps->topRight;i--)
printf("%d,",ps->data[i]);
}
int main()
{
SqStack sq ;
InitStack(&sq);
PushStack( &sq , 1 , 100) ;
PushStack( &sq , 1 , 200) ;
PushStack( &sq , 1 , 300) ;
PushStack( &sq , 1 , 400) ;
PopStack( &sq , 1 ) ;
PushStack( &sq , 2 , 10) ;
PushStack( &sq , 2 , 20) ;
PushStack( &sq , 2 , 30) ;
PushStack( &sq , 2 , 40) ;
PopStack( &sq , 2 ) ;
DisplayStack( &sq);
getchar();
}
/* reverse sequence practice : 3.17
** Author : kevin
** Date : 2012/02/24
*/
#include"stdio.h"
#include"stdlib.h"
#include"alloc.h"
typedef struct{
char data[50]; /*Store the data*/
int base ; /*The base pointer*/
int top ; /*The top pointer*/
}SqStack ;
/*Init the stack*/
void InitStack( SqStack *ps)
{
int i ;
for(i=0; i<50; i++){
ps->data[i] = '';
}
ps->base = 0;
ps->top = 0 ;
}
/*Push the value into stack*/
void PushStack( SqStack *ps , char c)
{
int n ;
n = ps->top ;
ps->data[n] = c;
ps->top++;
}
/*Pop the value */
char PopStack( SqStack *ps )
{
int n ;
char e ;
n = ps->top ;
e = ps->data[n];
ps->top--;
return e ;
}
void DisplayStack( SqStack *ps )
{
int i ;
for(i=0; itop;i++)
printf("%c,",ps->data[i]);
}
int main()
{
SqStack sq ;
char c ;
char result ;
int status = 0 ;
InitStack(&sq);
while( (c=getchar())!='@'){ --> 注意这的括号 ( ( c=getchar() ) != '@' )
if(c=='&'){
status = 1;
DisplayStack(&sq);
continue ;
}
if(status == 0 ){
PushStack(&sq,c);
}
else{
result = PopStack(&sq);
if(result==c){
continue ;
}
else{
printf("NG , This is a not matched model");
getchar();
return 0 ;
}
}
}
printf("This is a correct model");
getchar();
getchar();
}
/* bracket , practice 3.19
** Author : kevin
** Date : 2012/02/24
*/
#include"stdio.h"
#include"stdlib.h"
#include"alloc.h"
typedef struct{
char data[50]; /*Store the data*/
int base ; /*The base pointer*/
int top ; /*The top pointer*/
}SqStack ;
/*Init the stack*/
void InitStack( SqStack *ps)
{
int i ;
for(i=0; i<50; i++){
ps->data[i] = '';
}
ps->base = 0;
ps->top = 0 ;
}
/*Push the value into stack*/
void PushStack( SqStack *ps , char c)
{
int n ;
n = ps->top ;
ps->data[n] = c;
ps->top++;
}
/*Pop the value */
char PopStack( SqStack *ps )
{
int n ;
char e ;
n = ps->top -1 ;
e = ps->data[n];
ps->top--;
return e ;
}
/*display the stack*/
void DisplayStack( SqStack *ps )
{
int i ;
for(i=0; itop;i++)
printf("%c,",ps->data[i]);
}
int main()
{
SqStack sq ;
char c , result ;
InitStack( &sq );
while((c=getchar())!='\n'){
if(c =='[' || c =='(' || c =='{'){
PushStack(&sq,c);
}
else{
if(c==')'){
result = PopStack( &sq );
if(result=='('){
continue;
}else{
printf("NG , we can't match");
getchar();
getchar();
}
}
else if(c=='}'){
result = PopStack( &sq );
if(result=='{'){
continue;
}else{
printf("NG , we can't match");
getchar();
getchar();
}
}else{
result = PopStack( &sq );
if(result=='['){
continue;
}else{
printf("NG , we can't match");
getchar();
getchar();
}
}
}
}
printf("This is matched charactor");
getchar();
getchar();
}
/* A little difficult , Expression reverse practice 3.21
** Author : kevin
** Date : 2012/02/24
*/
/* The operater charactor precedence is ) * / + - ( */
#include"stdio.h"
#include"stdlib.h"
#include"alloc.h"
/*operate charactor stack*/
typedef struct {
char op[20]; /*Save operate charactor*/
int top ; /*top*/
int base ; /*base*/
}OpStack ;
/*s1 and s2*/
typedef struct {
char *s[20]; /*Save s1 and s2 , sample : s1+s2 */
int top ;
int base ;
}SpStack ;
/*Expression reverse*/
typedef struct{
char data[20] ; /*The result */
int dp ; /*The current pointer*/
}ExpResult;
void InitOpStack( OpStack * po )
{
int i ;
for(i=0; i<20; i++){
po->op[20] = '';
}
po->op[0] = '#';
po->base = 0;
po->top = 1;
}
void InitSpStack( SpStack * ps )
{
int i ;
for(i=0; i<20; i++)
ps->s[i] = (char *)malloc(sizeof(char));
ps->base = 0;
ps->top = 0 ;
}
void InitExpResult(ExpResult *pr)
{
int i ;
for(i=0; i<20; i++){
pr->data[i] = '';
}
pr->dp = 0 ;
}
void PushOpStack( OpStack * po , char e)
{
int n ;
n = po->top;
po->op[n] = e;
po->top++;
}
char PopOpStack( OpStack * po )
{
int n ;
char e ;
n = po->top -1;
e = po->op[n] ;
po->top--;
return e ;
}
void PushSpStack( SpStack * ps , char *pe , int count )
{
int n ,i ;
char *p;
p = pe;
*(p+count) = '\0';
n = ps->top;
strcpy(ps->s[n],p);
ps->top++;
}
char * PopSpStack( SpStack * ps )
{
int n ;
n = ps->top -1;
ps->top--;
return ps->s[n] ;
}
void DisplayExp( ExpResult *pe )
{
int i ;
for(i=0; i<=pe->dp; i++){
printf("%c",pe->data[i]);
}
}
void InsertExp( ExpResult *pe , char c )
{
int n ;
n = pe->dp ;
pe->data[n] = c;
pe->dp++;
}
int main()
{
int exp_dp;
int i ;
char c ;
char c_op ;
char *s1 = NULL ;
char *s2 = NULL ;
char *p = NULL ;
OpStack os ;
SpStack ss ;
ExpResult exp , exp_sub;
InitOpStack(&os);
InitSpStack(&ss);
InitExpResult( &exp );
InitExpResult( &exp_sub );
while((c=getchar())!='#'){
if( c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')' ){
switch(c){
case '+':
case '-':
if( os.op[os.top-1] == '#' || os.op[os.top-1] == '+' || os.op[os.top-1] == '-' || os.op[os.top-1] == '(' ){
PushOpStack(&os,c);
} /*precedence more than stack top , only push into stack*/
else{ /*precedence less than stack top , pop stack*/
s2 = PopSpStack(&ss);
s1 = PopSpStack(&ss);
c_op = PopOpStack(&os);
p = s1 ;
for(i=0 ; *(p+i)!= '\0';i++){
InsertExp(&exp,*(p+i));
}
p = s2 ;
for(i=0 ; *(p+i)!= '\0';i++){
InsertExp(&exp,*(p+i));
}
InsertExp(&exp,c_op);
}
break;
case '*':
case '/':
PushOpStack(&os,c);
break;
case '(':
PushOpStack(&os,c);
break;
case ')':
while( os.op[os.top - 1] !='('){
s2 = PopSpStack(&ss);
s1 = PopSpStack(&ss);
c_op = PopOpStack(&os);
p = s1 ;
for(i=0 ; *(p+i)!= '\0';i++){
InsertExp(&exp_sub,*(p+i));
}
p = s2 ;
for(i=0 ; *(p+i)!= '\0';i++){
InsertExp(&exp_sub,*(p+i));
}
InsertExp(&exp_sub,c_op);
PushSpStack(&ss,exp_sub.data,exp_sub.dp); /* Push again */
InitExpResult(&exp_sub);
}
if( PopOpStack(&os) =='('){
s1 =PopSpStack(&ss) ;
p = s1 ;
for(i=0 ; *(p+i)!= '\0';i++){
InsertExp(&exp,*(p+i));
}
}
break;
}
}else{
PushSpStack(&ss,&c,1);
}
}
while(ss.top!=0){ /*remain the s1 and s2 stack*/
s1 = PopSpStack(&ss);
p = s1 ;
for(i=0 ; *(p+i)!= '\0';i++){
InsertExp(&exp,*(p+i));
}
}
while(os.op[os.top]!='#'){ /*remain the s1 and s2 stack*/
c_op = PopOpStack(&os);
InsertExp(&exp,c_op);
}
printf("\n");
DisplayExp(&exp);
getchar();
getchar();
}
/* Circle Quene practice 3.28
** Author : kevin
** Date : 2012/02/27
*/
#include"stdio.h"
#include"alloc.h"
#include"stdlib.h"
typedef struct QNode{
int data ;
struct MyLinkQueue * next ;
}QNode , *QueuePtr ;
typedef struct {
QueuePtr rear ;
}*LinkQueue ;
LinkQueue InitQueue(){
LinkQueue pr ;
pr->rear = (QueuePtr)malloc(sizeof(QNode));
pr->rear->next = pr->rear ;
return pr ;
}
void InQueue( LinkQueue pr , int a ){
QueuePtr p ;
p = (QueuePtr)malloc(sizeof(QNode));
p->data = a ;
p->next = pr->rear->next ;
pr->rear->next = p ;
pr->rear = p ;
}
void OutQueue( LinkQueue pr ){
QueuePtr p ;
p = pr->rear->next->next ;
pr->rear->next->next = pr->rear->next->next->next ;
free(p);
}
void Display( LinkQueue pr ){
QueuePtr p = pr->rear->next->next ;
while( p!= pr->rear->next){
printf("%d,",p->data);
p = p->next ;
}
}
int main(){
LinkQueue pq ;
pq = InitQueue() ;
InQueue( pq , 1);
InQueue( pq , 2);
InQueue( pq , 3);
Display(pq);
OutQueue(pq);
Display(pq);
getchar();
}
7. 练习册 ( 3.31 )
/* huiwen Circle Queue practice 3.31
** Author : Kevin
** Date : 2012/02/27
*/
#include"stdio.h"
#include"alloc.h"
#include"stdlib.h"
/*Node struct*/
typedef struct QNode{
char data ; /*Save the data*/
struct QNode *next ; /*next pointer*/
struct QNode *prior ; /*prior pointer*/
}QNode , *QueuePtr ;
/*Queue struct*/
typedef struct {
QueuePtr phead ; /*head pointer*/
QueuePtr prear ; /*rear pointer*/
}*LinkQueue;
LinkQueue InitQueue(){
LinkQueue pr ;
pr->phead = (QueuePtr)malloc(sizeof(QNode));
pr->prear = pr->phead ;
pr->phead->next = pr->phead ;
pr->prear->prior = pr->prear ;
return pr ;
}
void InQueue( LinkQueue pr , char a ){
QueuePtr p ;
p = (QueuePtr)malloc(sizeof(QNode));
p->data = a ;
p->next = pr->prear->next ;
p->prior = pr->prear ;
pr->prear->next = p ;
pr->prear = p ;
}
void OutQueue( LinkQueue pr ){
QueuePtr p ;
p = pr->phead->next ;
p->next->prior = pr->phead ;
pr->phead->next = p->next ;
free(p);
}
void Huiwen(LinkQueue pr){
QueuePtr p , q ;
p = pr->phead->next ;
q = pr->prear;
while(p!=q){
if(p->data ==q->data){
}else{
printf("Not huiwen");
return 0;
}
p = p->next;
q = q->prior;
}
printf("This is huiwen ");
}
void Display( LinkQueue pr ){
QueuePtr p = pr->phead->next ;
while( p!= pr->phead){
printf("%d,",p->data);
p = p->next ;
}
}
int main(){
char c ;
LinkQueue pq ;
pq = InitQueue() ;
while((c=getchar())!='@'){
InQueue(pq,c);
}
Huiwen(pq);
getchar();
getchar();
}
/* huiwen Circle Queue practice 3.31
** Author : Kevin
** Date : 2012/02/27
*/
#include"stdio.h"
#include"alloc.h"
#include"stdlib.h"
/*Node struct*/
typedef struct QNode{
char data ; /*Save the data*/
struct QNode *next ; /*next pointer*/
struct QNode *prior ; /*prior pointer*/
}QNode , *QueuePtr ;
/*Queue struct*/
typedef struct {
QueuePtr phead ; /*head pointer*/
QueuePtr prear ; /*rear pointer*/
}*LinkQueue;
LinkQueue InitQueue(){
LinkQueue pr ;
pr->phead = (QueuePtr)malloc(sizeof(QNode));
pr->prear = pr->phead ;
pr->phead->next = pr->phead ;
pr->prear->prior = pr->prear ;
return pr ;
}
void InQueue( LinkQueue pr , char a ){
QueuePtr p ;
p = (QueuePtr)malloc(sizeof(QNode));
p->data = a ;
p->next = pr->prear->next ;
p->prior = pr->prear ;
pr->prear->next = p ;
pr->prear = p ;
}
void OutQueue( LinkQueue pr ){
QueuePtr p ;
p = pr->phead->next ;
p->next->prior = pr->phead ;
pr->phead->next = p->next ;
free(p);
}
void Huiwen(LinkQueue pr){
QueuePtr p , q ;
p = pr->phead->next ;
q = pr->prear;
while(p!=q){
if(p->data ==q->data){
}else{
printf("Not huiwen");
return 0;
}
p = p->next;
q = q->prior;
}
printf("This is huiwen ");
}
void Display( LinkQueue pr ){
QueuePtr p = pr->phead->next ;
while( p!= pr->phead){
printf("%d,",p->data);
p = p->next ;
}
}
int main(){
char c ;
LinkQueue pq ;
pq = InitQueue() ;
while((c=getchar())!='@'){
InQueue(pq,c);
}
Huiwen(pq);
getchar();
getchar();
}