赞
踩
1.栈:是只允许在一边进行插入或删除的顺序表。■特别之处在于只能在一端进行删除、插入。
2.栈顶:进行删除或插入操作的一端。
3.栈底:不能进行删除或插入的一端。
栈的实现可以用数组(顺序表),也可以使用链表,这里使用顺序表来实现。栈的常见操作有栈的初始化、销毁、增删等等,以下是栈创建过程中使用的函数。
不直接定义一个数组,而采用realloc、malloc来动态管理顺序表大小,使栈的大小不再受限。再定义一个top栈顶指针来方便后续的增删操作。
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<stdbool.h>
-
- typedef int MyDataType;//将int类型重定义叫做MyDataType
- typedef struct Stack
- {
- MyDataType* a;//一个MyDataType类型的指针,可以进行动态内存开辟
- int capacity;//栈的最大容量
- int top;//用于栈顶指针
- }ST;
在初始化中,将top栈顶指针指向0,但此时栈中没有元素(此时栈为空)。当然也可以将top初始化为-1,此时当top为0时栈中含有一个元素。
- ST st;//在测试代码中预先定义一个ST类型的变量
- void InitStack(ST* ps)
- {
- assert(ps);
- ps->a = NULL;
- ps->capacity = 0;
- ps->top = 0;//将栈顶指针指向0
- }
在插入数据前,需要判断ps指针是否为空,还要判断栈是否已经达到最大容量,如果size=capacity(栈已达到最大容量)就需要使用realloc扩容(注意:使用realloc函数时,若第一个参数为空,则函数返回一个开辟了指定大小的地址)。当top初始化为0时,先赋值,在++top;而当top初始化为-1时,先++top,再赋值。
- void PushStack(ST* ps, MyDataType x)
- {
- assert(ps);
- if (ps->top == ps->capacity)
- {
- int NewSize = ps->top == 0 ? 4 : ps->capacity * 2;//用三目运算符可以避免对top是否为零的两种情况进行讨论
- MyDataType* temp = (MyDataType*)realloc(ps->a, sizeof(MyDataType) * NewSize);
- if (temp == NULL)
- {
- perror("realloc");
- exit(-1);
- }
- ps->a = temp;
- ps->capacity = NewSize;
- }
- ps->a[ps->top] = x;
- ps->top++;//先赋值再将top加一
- }
- bool StackEmpty(ST* ps)
- {
- assert(ps);
- return ps->top == 0;//ps->top为0,表达式为真返回true
- }
删除栈顶元素之前首先需要判断栈是否为空,如果为空则不能删除元素。顺序表删除尾部元素十分简单,只需要将栈顶指针指向的位置减一即可。
- void PopStack(ST* ps)
- {
- assert(ps);
- assert(ps->top > 0);
- --ps->top;
- }
由于对top初始化时的值不同,计数的条件不同,所以读取个数的操作也由我们来书写,而不由使用者自己来判断。
- int StackSize(ST* ps)
- {
- assert(ps);
- assert(ps->top >= 0);
- return ps->top ;
- }
- MyDataType StackTop(ST* ps)
- {
- assert(ps);
- assert(ps->top > 0);//需要判断栈是否为空,为空则不能读取栈顶元素
- return ps->a[ps->top-1];
- }
销毁需要把动态开辟的空间全部释放,并将指针置为空。
- void DestroyStack(ST* ps)
- {
- assert(ps);
- free(ps->a);
- ps->a = NULL;
- ps->capacity = ps->top = 0;
- }
栈的特点是后入先出,与括号之间匹配判断一致
- typedef char MyDataType;
- typedef struct Stack
- {
- MyDataType* a;
- int capacity;
- int top;
- }ST;
-
- void InitStack(ST*ps);
- void PushStack(ST* ps,MyDataType x);
- void PopStack(ST* ps);
- void DestroyStack(ST* ps);
- bool StackEmpty(ST* ps);
- MyDataType StackTop(ST* ps);
- int StackSize(ST* ps);
- void InitStack(ST* ps)
- {
- assert(ps);
- ps->a = NULL;
- ps->capacity = 0;
- ps->top = 0;
- }
- void PushStack(ST* ps, MyDataType x)
- {
- assert(ps);
- if (ps->top == ps->capacity)
- {
- int NewSize = ps->top == 0 ? 4 : ps->capacity * 2;
- MyDataType* temp = (MyDataType*)realloc(ps->a, sizeof(MyDataType) * NewSize);
- if (temp == NULL)
- {
- perror("realloc");
- exit(-1);
- }
- ps->a = temp;
- ps->capacity = NewSize;
- }
- ps->a[ps->top] = x;
- ps->top++;
- }
- void PopStack(ST* ps)
- {
- assert(ps);
- assert(ps->top > 0);
- --ps->top;
- }
- void DestroyStack(ST* ps)
- {
- assert(ps);
- free(ps->a);
- ps->a = NULL;
- ps->capacity = ps->top = 0;
- }
- bool StackEmpty(ST* ps)
- {
- assert(ps);
- return ps->top == 0;
- }
- MyDataType StackTop(ST* ps)
- {
- assert(ps);
- assert(ps->top > 0);
- return ps->a[ps->top-1];
- }
- int StackSize(ST* ps)
- {
- assert(ps);
- assert(ps->top >= 0);
- return ps->top ;
- }//手动搭建一个栈
- bool isValid(char* s)
- {
- ST st;
- InitStack(&st);
- while(*s)
- {
- if(*s=='('||*s=='['||*s=='{')//当为左括号时入栈
- {
- PushStack(&st,*s);
- }
- else//当为右括号的时候
- {
- if(StackEmpty(&st))
- {
- DestroyStack(&st);
- return false;
- }//如果栈为空时就读取到右括号,
- //即说明还未有左括号就有右括号,显然不符合规律
- int stacktop=StackTop(&st);
- PopStack(&st);
- if(*s==')'&&stacktop!='('||
- *s==']'&&stacktop!='['||
- *s=='}'&&stacktop!='{' )//出栈并一一判断
- {
- DestroyStack(&st);
- return false;
- }
- }
- s++;
- }
- bool ret=StackEmpty(&st);
- return ret;
- }
队列是只允许在一端插入元素,另一端删除元素的线性表,特点是先进先出。
队列是从队尾进,队头出,所以采用链表的结构来实现,如果采用数组结构,则会使队头操作繁琐。与栈类似,我们仍然是实现以下函数代码。
Queue这个结构体中还包含两个QNode结点结构体。包含队列头尾结点,能够帮助从队尾插入和从队头删除。
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<stdbool.h>
-
- typedef int MyDataType;//将int类型重命名为MyDataType
- typedef struct QueueNode
- {
- MyDataType val;
- struct QueueNode* next;
- }QNode;//单链表的结点结构
-
- typedef struct Queue//队列中包含队头、队尾、队列大小
- {
- QNode* front;
- QNode* back;
- int size;
- }QL;
- void QueueInit(QL* pq)
- {
- assert(pq);//判断pq是否为空指针
- pq->size = 0;
- pq->front = pq->back = NULL;
- }
- void QueuePush(QL* pq, MyDataType x)
- {
- assert(pq);
- QNode* newnode = (QNode*)malloc(sizeof(QNode));
- if (newnode == NULL)
- {
- perror("malloc fail");
- exit(-1);
- }
- newnode->val = x;
- newnode->next = NULL;
- if (pq->back == NULL)
- pq->front = pq->back = newnode;//链表为空,则让front和back都指向newnode
- else
- {
- pq->back->next = newnode;
- pq->back = newnode;
- }
- pq->size++;
- }//与单链表搭建类似,由于不含头结点,
- //所以需要分链表是否为空的两种情况讨论。
- void QueuePop(QL* pq)//与单链表不同,这里不需要传二级指针,
- //因为这里只是修改结构体中的内容,而不是改变结构体地址
- {
- assert(pq);
- assert(!QueueEmpty(pq));//断言链表不为空,为空则不能删除数据
- if (pq->front->next == NULL)//链表只含有一个数据
- {
- free(pq->front);
- pq->back = pq->front = NULL;
- }
- else
- {
- QNode* cur = pq->front->next;
- free(pq->front);
- pq->front = cur;
- }
- pq->size--;
- }
- MyDataType QueueFront(QL* pq)//队头元素
- {
- assert(pq);
- assert(!QueueEmpty(pq));//不能为空链表
- return pq->front->val;
- }
- MyDataType QueueBack(QL* pq)//队尾元素
- {
- assert(pq);
- assert(!QueueEmpty(pq));//不能为空链表
- return pq->back->val;
- }
即使是读取队列元素个数这样的操作也靠函数实现,能有效避免使用者不明变量含义而造成读取元素个数错误。
- bool QueueEmpty(QL* pq)//判断队列是否为空
- {
- assert (pq);
- return pq->front==NULL;//若头结点为空,则队列不含任何元素,队列为空
- }
- int QueueSize(QL* pq)//读取队列大小
- {
- return pq->size;
- }
- void QueueDestroy(QL* pq)
- {
- assert(pq);
- QNode* cur = pq->front;
- while (cur)
- {
- QNode* next = cur->next;
- free(cur);
- cur = next;
- }//每个结点一一释放空间
- pq->back = pq->front = NULL;
- pq->size = 0;
- }
可以使用单链表和数组,但显然使用数组更方便。问题的关键在于数组尾元素的处理,这时要灵活使用取模操作。
-
- typedef struct {
- int *a;
- int front;
- int rear;
- int k;
- } MyCircularQueue;
-
-
- MyCircularQueue* myCircularQueueCreate(int k) {
- MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
- obj->k=k;
- obj->a=(int *)malloc(sizeof(int)*(k+1));
- obj->front=obj->rear=0;
- return obj;
- }
-
- bool myCircularQueueIsEmpty(MyCircularQueue* obj)
- {
- return obj->front==obj->rear;
- }
-
- bool myCircularQueueIsFull(MyCircularQueue* obj)
- {
- return (obj->rear+1)% (obj->k+1)==obj->front;
- }
-
-
- bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
- {
- if(myCircularQueueIsFull(obj))
- return false;
- obj->a[obj->rear]=value;
- obj->rear=(obj->rear+1)%(obj->k+1);
- return true;
- }
-
- bool myCircularQueueDeQueue(MyCircularQueue* obj)
- {
- if(myCircularQueueIsEmpty(obj))
- return false;
- obj->front=(obj->front+1)%(obj->k+1);
- return true;
- }
-
- int myCircularQueueFront(MyCircularQueue* obj)
- {
- if(myCircularQueueIsEmpty(obj))
- return -1;
- else
- return obj->a[obj->front];
- }
-
- int myCircularQueueRear(MyCircularQueue* obj) {
- if(myCircularQueueIsEmpty(obj))
- return -1;
- else
- return obj->a[(obj->rear+obj->k)%(obj->k+1)];
-
- }
-
- void myCircularQueueFree(MyCircularQueue* obj) {
- free(obj->a);
- free(obj);
-
- }
题目一:用栈实现队列
题目二:用队列实现栈
题目一:由于C语言没有库函数来搭建栈,所以我们必须手动搭建一个栈。思路很简单:用一个栈专门来进数据;另一个栈专门来出数据。
- typedef int MyDataType;
- typedef struct Stack
- {
- MyDataType* a;
- int capacity;
- int top;
- }ST;
-
- void InitStack(ST*ps);
- void PushStack(ST* ps,MyDataType x);
- void PopStack(ST* ps);
- void DestroyStack(ST* ps);
- bool StackEmpty(ST* ps);
- MyDataType StackTop(ST* ps);
- int StackSize(ST* ps);
- void InitStack(ST* ps)
- {
- assert(ps);
- ps->a = NULL;
- ps->capacity = 0;
- ps->top = 0;
- }
- void PushStack(ST* ps, MyDataType x)
- {
- assert(ps);
- if (ps->top == ps->capacity)
- {
- int NewSize = ps->top == 0 ? 4 : ps->capacity * 2;
- MyDataType* temp = (MyDataType*)realloc(ps->a, sizeof(MyDataType) * NewSize);
- if (temp == NULL)
- {
- perror("realloc");
- exit(-1);
- }
- ps->a = temp;
- ps->capacity = NewSize;
- }
- ps->a[ps->top] = x;
- ps->top++;
- }
- void PopStack(ST* ps)
- {
- assert(ps);
- assert(ps->top > 0);
- --ps->top;
- }
- void DestroyStack(ST* ps)
- {
- assert(ps);
- free(ps->a);
- ps->a = NULL;
- ps->capacity = ps->top = 0;
- }
- bool StackEmpty(ST* ps)
- {
- assert(ps);
- return ps->top == 0;
- }
- MyDataType StackTop(ST* ps)
- {
- assert(ps);
- assert(ps->top > 0);
- return ps->a[ps->top-1];
- }
- int StackSize(ST* ps)
- {
- assert(ps);
- assert(ps->top >= 0);
- return ps->top ;
- }
-
-
- typedef struct {
- ST pushstack;
- ST popstack;
- int size;
- } MyQueue;
-
-
- MyQueue* myQueueCreate()
- {
- MyQueue*queue=(MyQueue*)malloc(sizeof(MyQueue));
- InitStack(&queue->pushstack);
- InitStack(&queue->popstack);
- queue->size=0;
- return queue;
- }
-
- void myQueuePush(MyQueue* obj, int x)
- {
- assert(obj);
- PushStack(&obj->pushstack,x);
- }
-
- int myQueuePop(MyQueue* obj)
- {
- if(StackEmpty(&obj->popstack))
- {
- while(!StackEmpty(&obj->pushstack))
- {
- int push=StackTop(&obj->pushstack);
- PopStack(&obj->pushstack);
- PushStack(&obj->popstack,push);
- }
- }
- int pop=StackTop(&obj->popstack);
- PopStack(&obj->popstack);
- return pop;
- }
-
- int myQueuePeek(MyQueue* obj)
- {
- if(StackEmpty(&obj->popstack))
- {
- while(!StackEmpty(&obj->pushstack))
- {
- int push=StackTop(&obj->pushstack);
- PopStack(&obj->pushstack);
- PushStack(&obj->popstack,push);
- }
- }
- int pop=StackTop(&obj->popstack);
- return pop;
- }
-
- bool myQueueEmpty(MyQueue* obj)
- {
- return StackEmpty(&obj->pushstack)&&StackEmpty(&obj->popstack);
- }
-
- void myQueueFree(MyQueue* obj)
- {
- DestroyStack(&obj->pushstack);
- DestroyStack(&obj->popstack);
- free(obj);
- }
题目二:C语言仍然需要手动搭建队列。思路也不难:出数据时,现将数据导入另一个队列,只剩一个元素时,再弹出数据,如此反复。
- typedef int MyDataType;
- typedef struct QueueNode
- {
- MyDataType val;
- struct QueueNode* next;
- }QNode;
-
- typedef struct Queue
- {
- QNode* front;
- QNode* back;
- int size;
- }QL;
-
- void QueueInit(QL* pq);
- void QueueDestroy(QL* pq);
- void QueuePush(QL* pq, MyDataType x);
- void QueuePop(QL* pq);
- MyDataType QueueFront(QL* pq);
- MyDataType QueueBack(QL* pq);
- bool QueueEmpty(QL* pq);
- int QueueSize(QL* pq);
- void QueueInit(QL* pq)
- {
- assert(pq);
- pq->size = 0;
- pq->front = pq->back = NULL;
- }
- void QueueDestroy(QL* pq)
- {
- assert(pq);
- QNode* cur = pq->front;
- while (cur)
- {
- QNode* next = cur->next;
- free(cur);
- cur = next;
- }
- pq->back = pq->front = NULL;
- pq->size = 0;
- }
- void QueuePush(QL* pq, MyDataType x)
- {
- assert(pq);
- QNode* newnode = (QNode*)malloc(sizeof(QNode));
- if (newnode == NULL)
- {
- perror("malloc fail");
- exit(-1);
- }
- newnode->val = x;
- newnode->next = NULL;
- if (pq->back == NULL)
- pq->front = pq->back = newnode;
- else
- {
- pq->back->next = newnode;
- pq->back = newnode;
- }
- pq->size++;
- }
- void QueuePop(QL* pq)
- {
- assert(pq);
- assert(!QueueEmpty(pq));
- if (pq->front->next == NULL)
- {
- free(pq->front);
- pq->back = pq->front = NULL;
- }
- else
- {
- QNode* cur = pq->front->next;
- free(pq->front);
- pq->front = cur;
- }
- pq->size--;
- }
- MyDataType QueueFront(QL* pq)
- {
- assert(pq);
- assert(!QueueEmpty(pq));
- return pq->front->val;
- }
- MyDataType QueueBack(QL* pq)
- {
- assert(pq);
- assert(!QueueEmpty(pq));
- return pq->back->val;
- }
- bool QueueEmpty(QL* pq)
- {
- assert (pq);
- return pq->back==NULL;
- }
- int QueueSize(QL* pq)
- {
- return pq->size;
- }
-
-
- typedef struct {
- QL queue1;
- QL queue2;
- } MyStack;
-
-
- MyStack* myStackCreate() {
- MyStack*mystack=(MyStack*)malloc(sizeof(MyStack));
- QueueInit(&mystack->queue1);
- QueueInit(&mystack->queue2);
- return mystack;
- }
-
- void myStackPush(MyStack* obj, int x)
- {
- if(QueueEmpty(&obj->queue1))
- {
- QueuePush(&obj->queue2,x);
- }
- else{
- QueuePush(&obj->queue1,x);
- }
- }
-
- int myStackPop(MyStack* obj)
- {
- QL* empque=&obj->queue1;
- QL *noempque=&obj->queue2;
- if(QueueEmpty(&obj->queue2))
- {
- empque=&obj->queue2;
- noempque=&obj->queue1;
- }
- while(QueueSize(noempque)!=1)
- {
- int push=QueueFront(noempque);
- QueuePop(noempque);
- QueuePush(empque,push);
- }
- int pop=QueueFront(noempque);
- QueuePop(noempque);
- return pop;
- }
-
- int myStackTop(MyStack* obj) {
- if(!QueueEmpty(&obj->queue1))
- return QueueBack(&obj->queue1);
- else
- return QueueBack(&obj->queue2);
-
- }
-
- bool myStackEmpty(MyStack* obj) {
-
- return QueueEmpty(&obj->queue1)&&QueueEmpty(&obj->queue2);
-
- }
-
- void myStackFree(MyStack* obj) {
- free(obj);
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。