栈、队列基础面试题

一、实现一个栈,要求实现Push、Pop、MIn的时间复杂度为O(1)
1)对于栈来说,Push、Pop的时间复杂度本来就为O(1);
2)但返回最小值的时间复杂度则会上升到O(N);因为需要从头遍历

解决方法1:在每一次出入栈的同时,就将最小值存起来。用两个数(入栈值、最小值)表示一个整体;
(注意)此时,Top栈顶元素实际上为第二个元素的值。

typedef struct MinStack {
      Stack stack;
} MinStack;
SDatatype MinStackTop(MinStack *pMS)
{
      return StackNextTop(&(pMS->stack));
}
SDatatype MinStackMin(MinStack *pMS)
{
      return StackTop(&(pMS->stack));
}
void MinStackInit(MinStack *pMS)
{
      assert(pMS);
      StackInit(&pMS->stack);
}
//主要方面,压栈过程与出栈过程
void MinStackPush(MinStack *pMS,SDatatype data)
{
      SDatatype min;
      if (!StackIsEmpty(&pMS->stack) && StackTop(&pMS->stack) < data) {
            min = StackTop(&pMS->stack);
            StackPush(&pMS->stack, data);
            StackPush(&pMS->stack, min);
      }
      else {
            StackPush(&pMS->stack, data);
            StackPush(&pMS->stack, data);
      }
}
void MinStackPop(MinStack *pMS)
{
      StackPop(&pMS->stack);
      StackPop(&pMS->stack);
}
void MinStackDestory(MinStack *pMS)
{
      assert(pMS);
      StackDestory(&pMS->stack);
}

解决方法2:用两个栈实现一个栈,其中一个栈里存最小值,另外一个栈里存数据;1栈nomal 2栈min
(注意)入栈时:1栈正常入,2栈先判断,再决定入2栈
出栈时:先判断1栈和2栈的元素;若相同,则同时出1、2栈

typedef struct MinStack2 {
      Stack nomal;
      Stack min;
} MinStack2;
void MinStack2Init(MinStack2 *pMS)
{
      assert(pMS);
      StackInit(&pMS->nomal);
      StackInit(&pMS->min);
}
SDatatype MinStack2Top(MinStack2 *pMS)
{
      return StackTop(&pMS->nomal);
}
SDatatype MinStack2Min(MinStack2 *pMS)
{
      return StackTop(&pMS->min);
}
void MinStack2Destory(MinStack2 *pMS)
{
      StackDestory(&pMS->min);
      StackDestory(&pMS->nomal);
}
//主要方面,函数出入栈的实现
void MinStack2Push(MinStack2 *pMS,SDatatype data)
{
      assert(pMS);
      StackPush(&pMS->nomal, data);
      //注意先比较,再确定要不要将值入栈到最小栈里
      if (StackIsEmpty(&pMS->min) || MinStack2Min(pMS) >= data) {
            StackPush(&pMS->min, data);
      }
}
void MinStack2Pop(MinStack2 *pMS)
{
      assert(pMS);
      //出栈时注意:若最小栈和正常栈的数据不同,只出正常栈即可。
      if (MinStack2Min(pMS) == MinStack2Top(pMS)) {
            StackPop(&pMS->min);
      }
      StackPop(&pMS->nomal);
}

二、使用两个栈实现一个队列
1)这个问题涉及到数据在两个栈之间的转移:想要Pop,就必须要先移动数据;想要Top,必须要先移动数据;
2)这个问题的基础是先将stack1的数据清空。

typedef struct QueueBy2Stack {
      Stack stack1;
      Stack stack2;
} QueueBy2Stack;
void QueueBy2StackInit(QueueBy2Stack *pQ)
{
      StackInit(&pQ->stack1);
      StackInit(&pQ->stack2);
}
void QueueBy2StackDestory(QueueBy2Stack *pQ)
{
      StackDestory(&pQ->stack1);
      StackDestory(&pQ->stack2);
}
//正常的入栈到stack1;
void QueueBy2StackPush(QueueBy2Stack *pQ,SDatatype data)
{
      StackPush(&pQ->stack1, data);
}
//将stack1的数据清空;
//如果stack2中仍有数据,则什么都不做;
void QueueBy2StackMove(QueueBy2Stack *pQ)
{
      SDatatype data;
      if (StackIsEmpty(&pQ->stack2)) {
            while (!StackIsEmpty(&pQ->stack1)) {
                  data = StackTop(&pQ->stack1);
                  StackPush(&pQ->stack2, data);
                  StackPop(&pQ->stack1);
            }
      }
}
//先移动stack1中的数据-->stack2中,在stack2中进行Pop
void QueueBy2StackPop(QueueBy2Stack *pQ)
{
      QueueBy2StackMove(pQ);
      assert(!StackIsEmpty(&pQ->stack2));
      StackPop(&pQ->stack2);
}
//先移动stack中的数据-->stack2中,在stack2中进行Top
SDatatype QueueBy2StackTop(QueueBy2Stack *pQ)
{
      QueueBy2StackMove(pQ);
      assert(!StackIsEmpty(&pQ->stack2));
      StackTop(&pQ->stack2);
}
void TestQueueBy2Stack()
{
      QueueBy2Stack queue;
      QueueBy2StackInit(&queue);
      QueueBy2StackPush(&queue, 1);
      QueueBy2StackPush(&queue, 2);
      QueueBy2StackPush(&queue, 3);
      QueueBy2StackPush(&queue, 4);
      QueueBy2StackPush(&queue, 5);
      printf("%d\n", QueueBy2StackTop(&queue));
      QueueBy2StackPop(&queue);
      printf("%d\n", QueueBy2StackTop(&queue));
      QueueBy2StackPop(&queue);
      printf("%d\n", QueueBy2StackTop(&queue));
      QueueBy2StackPop(&queue);
      printf("%d\n", QueueBy2StackTop(&queue));
      QueueBy2StackPop(&queue);
      printf("%d\n", QueueBy2StackTop(&queue));
      QueueBy2StackPop(&queue);
      QueueBy2StackDestory(&queue);
}

三、使用两个队列实现一个栈
1)实际上也是利用两个队列之间来回转移数据,实现栈的基本功能。
2)Push:直接往非空队列里面插入;
3)Pop:先确定空队列和非空队列;再将非空队列中的数据转移到空队列;剩余最后一个数据(QueueSize>1)时,直接Pop;
4)Top:先确定空队列和非空队列;再将非空队列中的数据转移到空队列;剩余最后一个数据(QueueSize>1)时,将最后一个数据取出来存着,再将其放入空队列中;return 存着的;

typedef struct StackBy2Queue {
      Queue queue1;
      Queue queue2;
} StackBy2Queue;
void StackBy2QueueInit(StackBy2Queue *pS)
{
      QueueInit(&pS->queue1);
      QueueInit(&pS->queue2);
}
void StackBy2QueueDestory(StackBy2Queue *pS)
{
      QueueDestory(&pS->queue1);
      QueueDestory(&pS->queue2);
}
//先确定空队列和非空队列;再Push进非空队列;
void StackBy2QueuePush(StackBy2Queue *pQ,QDatatype data)
{
      Queue *NotEmpty = &pQ->queue1;
      Queue *Empty = &pQ->queue2;
      if (!QueueIsEmpty(Empty)) {
            NotEmpty = &pQ->queue2;
            Empty = &pQ->queue1;
      }
      QueuePush(NotEmpty, data);
}
//先确定空队列和非空队列;再将非空队列中的数据转移到空队列;
//最后,当剩余最后一个数据时(QueueSize>1),将其Pop出去;
void StackBy2QueuePop(StackBy2Queue *pQ)
{
      QDatatype data;
      Queue *NotEmpty = &pQ->queue1;
      Queue *Empty = &pQ->queue2;
      if (!QueueIsEmpty(Empty)) {
            NotEmpty = &pQ->queue2;
            Empty = &pQ->queue1;
      }
      while (QueueSize(NotEmpty) > 1) {
            data = QueueFront(NotEmpty);
            QueuePop(NotEmpty);
            QueuePush(Empty, data);
      }
      QueuePop(NotEmpty);
}
//先确定空队列和非空队列;再将非空队列中的数据转移到空队列;
//当剩余最后一个数据时(QueueSize>1),将其保存起来,然后将其再放入空队列中;
//最后,直接返回return 保存的数据;
QDatatype StackBy2QueueFront(StackBy2Queue *pQ)
{
      QDatatype data;
      Queue *NotEmpty = &pQ->queue1;
      Queue *Empty = &pQ->queue2;
      if (!QueueIsEmpty(Empty)) {
            NotEmpty = &pQ->queue2;
            Empty = &pQ->queue1;
      }
      while (QueueSize(NotEmpty) > 1) {
            data = QueueFront(NotEmpty);
            QueuePop(NotEmpty);
            QueuePush(Empty, data);
      }
      data = QueueFront(NotEmpty);
      QueuePop(NotEmpty);
      QueuePush(Empty, data);
      return data;
}
void TestStackBy2Queue()
{
      StackBy2Queue stack;
      StackBy2QueueInit(&stack);
      StackBy2QueuePush(&stack, 1);
      StackBy2QueuePush(&stack, 2);
      StackBy2QueuePush(&stack, 3);
      StackBy2QueuePush(&stack, 4);
      printf("%d\n", StackBy2QueueFront(&stack));
      StackBy2QueuePop(&stack);
      printf("%d\n", StackBy2QueueFront(&stack));
      StackBy2QueuePop(&stack);
      printf("%d\n", StackBy2QueueFront(&stack));
      StackBy2QueuePop(&stack);
      printf("%d\n", StackBy2QueueFront(&stack));
      StackBy2QueuePop(&stack);
      StackBy2QueueDestory(&stack);
}

四、一个数组实现两个栈(共享栈)

#define CAPACITY (4)
typedef int DataType;
typedef struct ShareStack {
      DataType *array;
      int capacity;
      int top1;
      int top2;
} ShareStack;
void ShareStackInit(ShareStack *pS)
{
      assert(pS);
      pS->array = (DataType *)malloc(sizeof(DataType)* CAPACITY);
      pS->capacity = CAPACITY;
      pS->top1 = 0;
      pS->top2 = pS->capacity - 1;
}
void ShareStackDestory(ShareStack *pS)
{
      assert(pS);
      free(pS->array);
      pS->array = NULL;//防止野指针的出现
      pS->capacity = 0;
      pS->top1 = 0;
      pS->top2 = 0;
}
void ExpendIfRequired(ShareStack *pS)
{
      assert(pS);
      if (pS->top1 - 1 != pS->top2) {
            return;
      }
      int oldcapacity = pS->capacity;
      pS->capacity *= 2;
      DataType *NewArray = (DataType *)malloc(sizeof(DataType)* pS->capacity);
      memset(NewArray, 0x00, sizeof(DataType)*pS->capacity);
      int Stack2Size = oldcapacity - 1 - pS->top2;
      memcpy(NewArray, pS->array, sizeof(DataType)*pS->top1);
      memcpy(NewArray + pS->capacity - Stack2Size, pS->array + pS->top2, sizeof(DataType)*Stack2Size);
      pS->top2 = pS->capacity - 1 - Stack2Size;
      free(pS->array);
      pS->array = NewArray;
}
void ShareStackPush(ShareStack *pS, int which, DataType data)
{
      assert(pS);
      ExpendIfRequired(pS);
      if (which == 1) {
            pS->array[pS->top1++] = data;
      }
      if (which == 2) {
            pS->array[pS->top2--] = data;
      }
}
void ShareStackPop(ShareStack *pS, int which)
{
      assert(pS);
      if (which == 1) {
            assert(pS->top1 > 0);
            pS->top1--;
      }
      if (which == 2) {
            assert(pS->top2 < pS->capacity - 1);
            pS->top2++;
      }
}
DataType ShareStackTop(ShareStack *pS, int which)
{
      assert(pS);
      if (which == 1) {
            assert(pS->top1 > 0);
            return pS->array[pS->top1 - 1];
      }
      if (which == 2) {
            assert(pS->top2 < pS->capacity - 1);
            return pS->array[pS->top2 + 1];
      }
}
void TestShareStack()
{
      ShareStack stack;
      ShareStackInit(&stack);
      int i = 0;
      ShareStackPush(&stack, 1, 1);
      ShareStackPush(&stack, 1, 2);
      ShareStackPush(&stack, 1, 3);
      ShareStackPush(&stack, 2, 4);
      ShareStackPush(&stack, 2, 5);
      ShareStackPush(&stack, 2, 16);
      ShareStackPush(&stack, 2, 17);
      for (i = 0; i < 3; i++) {
            printf("%d\n", ShareStackTop(&stack, 1));
            ShareStackPop(&stack, 1);
      }
      for (i = 0; i < 4; i++) {
            printf("%d\n", ShareStackTop(&stack, 2));
            ShareStackPop(&stack, 2);
      }
      ShareStackDestory(&stack);
}

你可能感兴趣的:(C++,栈,队列)