今天学习了数据结构中栈,队列的知识
相对于单链表来说,栈和队列就是添加的方式不同,队列就相当于排队,先排队的先出来(FIFO),而栈就相当于弹夹,先压进去的子弹后出来(FILO)。
首先看一下栈(Stack)的实现
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define TRUE 1 4 #define FALES 0 5 typedef struct NODE 6 { 7 int i; 8 struct NODE *pNext; //指向的是 上一个从栈顶刚压入的结点 9 }Stack; 10 typedef int BOOL; //因为c语言里没有布尔类型,所以用int模拟一下 11 void Push(Stack **pTop,int i); 12 BOOL IfEmpty(Stack *pTop); 13 Stack *Pop(Stack **pTop); //出栈操作 14 int main() 15 { 16 Stack *pTop = NULL; 17 18 19 } 20 void Push(Stack **pTop,int i) //压栈操作 21 { 22 Stack *pTemp = (Stack *)malloc(sizeof(Stack)); 23 pTemp->i = i; 24 pTemp->pNext = NULL; 25 26 pTemp->pNext = *pTop; 27 *pTop = pTemp; 28 29 return; 30 } 31 BOOL IfEmpty(Stack *pTop) //因为c++的STL容器里存在判断栈是否为空的操作,在这模拟一下 32 { 33 if(pTop == NULL) 34 return TRUE; 35 return FALES; 36 } 37 Stack *Pop(Stack **pTop) 38 { 39 Stack *pPop = NULL; 40 if(IfEmpty(*pTop)) 41 { 42 return NULL; 43 } 44 else 45 { 46 pPop = *pTop; 47 *pTop = (*pTop)->pNext; 48 return pPop; 49 } 50 }
其次队列(Queue)的实现非常简单,队列压入的实现就和单链表尾添加一样,而弹出就和单链表头删除是一样的,只不过不需要free直接返回队首指针即可;
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define TRUE 1 4 #define FALSE 0 5 typedef struct NODE 6 { 7 int i; 8 struct NODE *pNext; 9 }Queue; 10 typedef int BOOL; 11 int GetId(); 12 void QueueIn(Queue **ppHead,Queue **ppEnd); 13 BOOL IfEmpty(Queue *pHead); 14 Queue *QueueOut(Queue **ppHead,Queue **ppEnd); 15 int main() 16 { 17 Queue *pHead = NULL; 18 Queue *pEnd = NULL; 19 Queue *p = NULL; 20 21 QueueIn(&pHead,&pEnd); 22 QueueIn(&pHead,&pEnd); 23 QueueIn(&pHead,&pEnd); 24 p = QueueOut(&pHead,&pEnd); 25 26 return 0; 27 28 } 29 int GetId() 30 { 31 static int i = 0; 32 i++; 33 return i; 34 } 35 void QueueIn(Queue **ppHead,Queue **ppEnd) 36 { 37 Queue *pTemp = (Queue *)malloc(sizeof(Queue)); 38 pTemp->i = GetId(); 39 pTemp->pNext = NULL; 40 41 if(*ppHead == NULL) 42 { 43 *ppHead = pTemp; 44 } 45 else 46 { 47 (*ppEnd)->pNext = pTemp; 48 } 49 *ppEnd = pTemp; 50 } 51 BOOL IfEmpty(Queue *pHead) 52 { 53 if(pHead == NULL) 54 return TRUE; 55 return FALSE; 56 } 57 Queue *QueueOut(Queue **ppHead,Queue **ppEnd) 58 { 59 Queue *pOut = NULL; 60 if(IfEmpty(*ppHead) == TRUE) 61 return NULL; 62 else 63 { 64 pOut = *ppHead; 65 *ppHead = (*ppHead)->pNext; 66 return pOut; 67 } 68 }
那么栈和栈区又有什么区别呢?先看这样一段程序
1 #include<stdio.h> 2 int main() 3 { 4 int i = 1; 5 printf("%d %d ",i,i++); 6 7 return 0; 8 }
可能一打眼看 就认为是1 1,但测试后发现是 2 1,这就不免让人联想到先进后出的特点了,由于printf是一个标准输出库函数,i 和 i++都算做是两个实参,在函数中,形参也是一个局部变量,在函数这个堆区中存在,按照图中出栈的顺序先B后A,那么先 i++ 出来为 1 ,i 其次出来就为2了(启示就是,在栈区中 若一个函数的参数用了同一个变量 ,记得栈的特点)
双向链表,故名思意就是有一个链表可正向可反向,也就是在添加每个结点的时候,加入一个指针,指向上一个结点的地址,代码如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 typedef struct NODE 4 { 5 int id; 6 struct NODE *pNext; 7 struct NODE *pLast; //指向上个结点 8 }List; 9 void AddNode(List **ppHead,List **ppEnd,int id); 10 int main() 11 { 12 List *pHead = NULL; 13 List *pEnd = NULL; 14 AddNode(&pHead,&pEnd,1); 15 AddNode(&pHead,&pEnd,2); 16 AddNode(&pHead,&pEnd,3); 17 AddNode(&pHead,&pEnd,4); 18 19 while(pHead) 20 { 21 printf("%d ",pHead->id); 22 pHead = pHead->pNext; 23 } 24 printf(" "); 25 26 27 while(pEnd) 28 { 29 printf("%d ",pEnd->id); 30 pEnd = pEnd->pLast; 31 } 32 33 34 } 35 void AddNode(List **ppHead,List **ppEnd,int id) 36 { 37 List *pTemp = (List *)malloc(sizeof(List)); 38 pTemp->id = id; 39 pTemp->pLast = NULL; 40 pTemp->pNext = NULL; 41 42 if(*ppHead == NULL) 43 { 44 *ppHead = pTemp; 45 *ppEnd = pTemp; 46 } 47 else 48 { 49 (*ppEnd)->pNext = pTemp; 50 pTemp->pLast = *ppEnd; 51 *ppEnd = pTemp; 52 } 53 return; 54 }
最后看到了有两个小问题
第一个 如何用两个栈实现一个队列 这个很简单,先全部压入第一个栈里,然后弹出再压出第二个栈里,最后弹出的就是队列的顺序,反反得正
1 #include<stdio.h> 2 #include<stdlib.h> 3 typedef struct NODE 4 { 5 int id; 6 struct NODE *pNext; 7 } 8 Stack; 9 void Push1(Stack **pTop1); 10 Stack *Pop1(Stack **pTop1); 11 void Push2(Stack **pTop2,Stack *pNode); 12 Stack *Pop2(Stack **pTop2); 13 Stack *QueueOut(Stack **pTop1,Stack **pTop2); 14 void InitStack(Stack **pTop1,int n); 15 int IfEmpty(Stack *pTop1); 16 int GetId(); 17 int main() 18 { 19 Stack *pTop1 = NULL; 20 Stack *pTop2; 21 Stack *pTemp = NULL; 22 InitStack(&pTop1,5); 23 pTemp = QueueOut(&pTop1,&pTop2); 24 while(pTop2) 25 { 26 pTemp = QueueOut(&pTop1,&pTop2); 27 } 28 29 30 31 return 0; 32 } 33 int GetId() 34 { 35 static int i = 0; 36 i++; 37 return i; 38 } 39 void InitStack(Stack **pTop1,int n) 40 { 41 int i; 42 for(i = 0;i < n;i++) 43 { 44 Push1(pTop1); 45 } 46 return; 47 } 48 void Push1(Stack **pTop1) 49 { 50 Stack *pTemp = (Stack *)malloc(sizeof(Stack)); 51 pTemp->id = GetId(); 52 pTemp->pNext = NULL; 53 54 pTemp->pNext = *pTop1; 55 *pTop1 = pTemp; 56 57 return; 58 } 59 Stack *Pop1(Stack **pTop1) 60 { 61 Stack *pPop = NULL; 62 if(*pTop1 == NULL) 63 { 64 return NULL; 65 } 66 else 67 { 68 pPop = *pTop1; 69 *pTop1 = (*pTop1)->pNext; 70 return pPop; 71 } 72 } 73 void Push2(Stack **pTop2,Stack *pNode) 74 { 75 pNode->pNext = *pTop2; 76 *pTop2 = pNode; 77 78 return; 79 80 } 81 Stack *Pop2(Stack **pTop2) 82 { 83 Stack *pPop = NULL; 84 if(*pTop2 == NULL) 85 { 86 return NULL; 87 } 88 else 89 { 90 pPop = *pTop2; 91 *pTop2 = (*pTop2)->pNext; 92 return pPop; 93 } 94 } 95 int IfEmpty(Stack *pTop1) 96 { 97 if(pTop1 == NULL) 98 return 1; 99 return 0; 100 } 101 Stack *QueueOut(Stack **pTop1,Stack **pTop2) 102 { 103 while(IfEmpty(*pTop1) != 1) 104 Push2(pTop2,Pop1(pTop1)); 105 106 return Pop2(pTop2); 107 }
第二个,如何快速的找到链表里倒数第n个结点,设置两个指针指向头,一个先往后走k个结点,然后一起走,当先走的那个到达尾结点时,后走的也就是倒数第k个结点了
1 #include<stdio.h> 2 #include<stdlib.h> 3 typedef struct NODE 4 { 5 int id; 6 struct NODE *pNext; 7 }List; 8 int GetId(); 9 void AddNode(List **ppHead,List **ppEnd); 10 List *Search(List *pHead,List *pEnd,int n); 11 int main() 12 { 13 List *pHead = NULL; 14 List *pEnd = NULL; 15 List *pTemp = NULL; 16 int i; 17 for(i = 0;i < 5;i++) 18 AddNode(&pHead,&pEnd); 19 pTemp = Search(pHead,pEnd,2); 20 printf("%d ",pTemp->id); 21 22 } 23 int GetId() 24 { 25 static int i = 0; 26 i++; 27 return i; 28 } 29 void AddNode(List **ppHead,List **ppEnd) 30 { 31 List *pTemp = (List *)malloc(sizeof(List)); 32 pTemp->id = GetId(); 33 pTemp->pNext = NULL; 34 35 if(*ppHead == NULL) 36 { 37 *ppHead = pTemp; 38 } 39 else 40 { 41 (*ppEnd)->pNext = pTemp; 42 43 } 44 *ppEnd = pTemp; 45 } 46 List *Search(List *pHead,List *pEnd,int n) 47 { 48 int i; 49 List *pFast = pHead; 50 List *pSlow = pHead; 51 for(i = 0;i < n;i++) 52 { 53 pFast = pFast->pNext; 54 } 55 while(pFast) 56 { 57 pSlow = pSlow->pNext; 58 pFast = pFast->pNext; 59 } 60 return pSlow; 61 62 }
2019-04-29 22:32:52 编程菜鸟自我反省,大佬勿喷,谢谢!!!