1. 程式人生 > >棧和佇列面試題

棧和佇列面試題

採用順序棧實現棧基本操作; 採用鏈式佇列實現佇列基本操作;

#define MAXSIZE100;

typedef int SDataType;

typedef struct Stack
{
	SDataType array[MAXSIZE];
	int top;
}Stack;

typedef struct MinStack
{
	Stack data;
	Stack min;
}MinStack;

void StackInit(Stack *s)
{
	assert(s);
	s->top = 0;
}

void StackPush(Stack *s,SDataType data)
{	
	assert(s);
	if(MAXSIZE == s->top)
	{
		return;
	}
	s->array[s->top++] = data;
}

void StackPop(Stack *s)
{
	assert(s);
	if(StackEmpty(&s))
	{
		return;
	}
	ps->top--;
}

int StackEmpty(Stack *s)
{	
	assert(s);
	return 0==s->top;
}

int StackTop(Stack *s)
{
	assert(s);
	return s->array[s->top];
}

int StackSize(Stack *s)
{
	assert(s);
	return s->top;
}

一、實現一個棧,要求Push(入棧),Pop(出棧),Min(返回最小值)的時間複雜度為O(1),假設有min棧、data棧。 (1)入棧:將資料壓入data棧中,如果min棧為空或者該資料小於min棧棧頂元素,同時壓入min棧中。 (2)出棧:檢測data棧頂元素與min棧頂元素是否相同,若相同,min棧頂元素與data棧頂元素同時出棧,若不相同,只有data棧頂元素出棧。

void MinStackInit(MinStack *ms)
{
	assert(ms);
	StackInit(*ms->min);
	StackInit(*ms->data);
}

void MinStackPush(MinStack *ms,SDataType data)
{
	assert(ms);
	iStackPush(&ms->data,data);
	if(StackEmpty(&ms->min)||data<StackTop(&ms->min))
	{
		StackPush(&ms->min,data);
	}
}

void MinStackPop(MinStack *ms)
{
	assert(ms);
	if(StackEmpty(&ms->data))
		return;
	if(StackTop(&ms->min)==StackTop(&ms->data))
	{
		StackPop(&ms->min);
	}
	
	StackPop(&ms->data);
}

void MInStackEmpty(MinStack *ms)
{
	return 0==StackEmpty(&ms->data);
}

SDataType MinStackTop(MinStack *ms)
{
	return StackTop(&ms->data);
}

SDataType MinStackMin(MinStack *ms)
{
	return StackTop(&ms->min);
}

int MinStackSize(MinStack *s)
{
	return StackSize(&ms->data);
}

二、使用兩個棧實現一個佇列。stack1棧頂:佇列隊尾 stack2棧頂:佇列隊頭 。 (1)入隊,直接對stack1壓棧。 (2)出隊:檢測stack2是否有資料。 step1:stack2有元素,直接彈出。 step2:stack2沒有元素,將stack1資料“倒入”stack2,轉到step1。 (3) 取隊頭元素:取stack2棧頂元素。 step1:stack2有元素,直接彈出。 step2:stack2沒有元素,將stack1資料“倒入”stack2,轉到step1。 (4) 取隊尾元素:取stack1棧頂元素。 step1:stack1有元素,直接彈出。 step2:stack1沒有元素,將stack2資料“倒入”stack1,轉到step1。

typedef struct QueueBy2Stack
{
	Stack s1;
	Stack s2;
}QueueBy2Stack;
void QueueBy2StackInit(QueueBy2Stack *q)
{
	assert(q);
	StackInit(&q->s1);
	StackInit(&q->s2);
}

void QueueBy2StackPush(QueueBy2Stack *q,SDataType data)
{
	assert(q);
	StackPush(&q->s1);
}

void QueueBy2StackPop(QueueBy2Stack *q)
{
	assert(q);
	if(QueueBy2StackEmpty(q))
	  return;
	 
	 if(StackEmpty(&q->s2))
	 {
	 	while(!StackEmpty(&q->s1))
	 	{
	 		StackPush(&q->s2,StackTop(&q->s1));
	 		StackPop(&q->s1);
	 	}
	 }
	 StackPop(&q->s2);
}

int QueueBy2StackEmpty(QueueBy2Stack *q)
{
	return StackEmpty(&q->s1)&&StackEmpty(&q->s2);
}

SDataType QueueBy2StackFront(QueueBy2Stack *q)
{
	assert(q);
	if(StackEmpty(&q->s2))
	{
		while(!StackEmpty(&q->s1)
		{
			StackPush(&q->s2,StackTop(&q->s1));
			StackPop(&q->s1);
		}
	}
	return StackTop(&q->s2);
}

SDataType QueueBy2StackBack(QueueBy2Stack *q)
{
	assert(q);
	if(StackEmpty(&q->s1))
	{
		while(!StackEmpty(&q->s2))
		{
			StackPush(&q->s1,StackTop(&q->s2));
			StackPop(&p->s2);
		}
	}
	return StackTop(&q->s1);
}

int QueueBy2StackSize(QueueBy2Stack *q)
{
	assert(q);
	return StackSize(&q->s1)+StackSize(&q->s2);
}

三、使用兩個佇列實現一個棧。 (1) 壓棧:檢測那個佇列有資料,將資料放到該佇列。 (2) 出棧:檢測那個佇列有資料,將除隊尾的的資料匯入另一個佇列中,最後刪除隊尾。 (3) 返回有資料的隊尾節點。(前提是資料在一個佇列中)

typedef int QDataType;

typedef struct QListNode
{
	struct QListNode *next;
	QDataType data;	
}QListNode;

typedef struct Queue
{
	QListNode* front;
	QListNode* rear;
	QDataType sz;
}Queue;
QListNode *BuyNewNode(QDataType data)
{
	QListNode* newNode = (QListNode *)malloc(sizeof(QListNode));
	if(NULL == newNode)
	{
		return NULL;
	}
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

void QueueInit(Queue* q)
{
	assert(q);
	q->front = q->rear = BuyNewNode(0);
	q->sz = 0;
}

void QueuePush(Queue* q,QDataType data)
{
	assert(q);
	q->rear->next = BuyNewNode(data);
	q->rear = q->rear->next;
	q->sz++;
}

void QueuePop(Queue* q)
{
	assert(q);
	if(q->front != q->rear)
	{	
		QListNode* pDel = q->front->next;
		q->front->next = pDel->next;
		q->sz--;
		free(pDel);
		pDel = NULL:
	}
}

QDataType QueueFront(Queue* q)
{	
	assert(q);
	return q->front->next->data;
}

QDataType QueueBack(Queue* q)
{
	assert(q);
	return q->rear->data;
}

int QueueSize(Queue* q)
{
	assert(q);
	return q->sz;
}

int QueueEmpty(Queue* q)
{	
	assert(q);
	return 0==QueueSize(q);
}

//////////////////////////////////
//以上為佇列的基本操作;
//以下為兩個佇列實現的棧的操作;
//////////////////////////////////
typedef struct StackBy2Queue
{	
	Queue q1;
	Queue q2;
}StackBy2Queue;

void StackBy2QueueInit(StackBy2Queue* s)
{
	assert(s);
	QueueInit(s->q1);
	QueueInit(s->q2);
}

void StackBy2QueuePush(StackBy2Queue* s,QDataType data)
{
	assert(s);
	if(QueueSize(&s->q1))
	{	
		QueuePush(&s->q1,data);
	}
	else
	{
		QueuePush(&s->q2,data);
	}
}

void StackBy2QueuePop(StackBy2Queue* s)
{
	assert(s);
	if(QueueSize(&s->q1))
	{
		while(QueueSize(&s->q1)>1)
		{
			QueuePush(&s->q2,QueueFront(&s->q1));
			QueuePop(&s>q1);
		}
		QueuePop(&s->q1);
	}
	else
	{
		while(QueueSize(&s->q2)>1)
		{
			QueuePush(&s->q1,QueueFront(&s->q2));
			QueuePop(&s>q2);
		}
		QueuePop(&s->q2);
	}
}

QDataType StackBy2QueueTop(StackBy2Queue *s)
{
	assert(s);
	if(QueueSize(&s->q1)
	{
		return QueueBack(&s->q1);
	}
	else
	{	
		return QueueBack(&s->q2);
	}
}

四、判斷入棧出棧的合法性。 (1)按順序將入棧序列的元素壓入stack中。 (2)比較stack棧頂元素與出棧序列的元素,若相同,則進行(3),若不同則進行(1)。 (3)彈出stack棧頂元素,出棧序列向後移。 (4)此迴圈完成後,判斷stack棧是否為空,若為空,則順序正確,否則是錯誤的。

int InAndOutIsLegal(int *in,int *out,int insz,int outsz)
{
	assert(in && out);
	if(insz != outsz)
	{
		return 0;
	}
	stack s;
	StackInit(&s);
	int in_index = 0;
	int out_index = 0;
	for(;in_index < insz;in_index++)
	{
		StackPush(&s,in[in_index]);
		while(StackSize(&s) && StackTop(&s) == out[out_index])
		{
			StackPop(&s);
			out_index++;
		}
	}
	if(StackSize(&s))
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

五、一個數組實現兩個棧,有三種實現方法。 (1)奇偶儲存法。 (2)中點向兩邊逼近。 (3)兩邊向中點逼近。 簡單比較:如果兩個棧的元素個數相差較大(2)(3)效果一樣,(1)的空間利用率較低。我就用第(3)種方法了。

typedef struct ShareStack
{
	int array[MAXSIZE];
	int top1;
	int top2;
}ShareStack;
void ShareStackInit(ShareStack *s)
{
	assert(s);
	s->top1 = 0;
	s->top = MAXSIZE-1;
}

void ShareStackPush(ShareStack *s,SDataType data,int which)
{
	assert(s);
	if(1 == which)
	{
		s->array[s->top1++] = data;
	}
	else
	{
		s->array[s->top2--] = data;
	}
}

void ShareStackPop(ShareStack *s,int which)
{
	assert(s);
	if(1 == which)
	{
		if(s->top1>0)
			s->top1--;
	}
	else
	{
		if(s->top2<MAXSIZE)
			s->top2++;
	}
}

SDataType ShareStackTop(ShareStack *s,int which)
{
	assert(s);
	if(1 == which)
	{
		return s->array[s->top1--];
	}
	else
	{
		return s->array[s->top2++];
	}
} 

int ShareStackSIze(ShareStack *s,int which)
{
	assert(s);
	if(1 == which)
	{
		return s->top1;
	}
	else
	{
		return MAXSIZE-s->top2-1;
	}
}

int ShareStackEmpty(ShareStack *s,int which)
{
	return 0 == ShareStackSIze(s,which);
}

可能有些知識點掌握不到位,還請各位讀者在評論區多給意見!!!