栈结构的存储实现 附算法面试题

264 阅读7分钟

本环节代码大量,还请海涵

循环队列的链表实现

1 .0链表队列定义

#include "math.h"
#include "time.h"
#include "stdlib.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int ElementType;
typedef int Index;

//定义节点
typedef struct Chain{
ElementType type;
struct Chain *next;
}Chain;
typedef struct StackNode{
Chain *front;
Chain *real;
int count;
}StackNode;
typedef int Status;

1.1 队列初始化 

Status InitNode(StackNode *Node){
Node->front = NULL;
Node->real = NULL;
Node->count = 0;
return OK;
}

1.2 判断队列是否为空

Status IsEmpty(StackNode Node){
if (Node.count==0) {
printf("is empty ");
return TRUE;
}
printf("no empty ");
return FALSE;
}

1.3 清空队列

Status BecomeEmpty(StackNode *Node){
if (IsEmpty(*Node)) {
return TRUE;
}
int cc = Node->count;
Chain *chain = Node->front;
while (cc<1) {
Chain *tabp = chain;
chain = tabp->next;
free(tabp);
cc--;
}
return TRUE;
}

1.4 判断队列长度

int NodeLength(StackNode Node){
if (IsEmpty(Node)) {
printf("length:0 \n");
return 0;;
}
printf("length:%d \n",Node.count);
return Node.count;
}

1.5 获取队头

Status GetNodeHead(StackNode node,ElementType *type){
if (IsEmpty(node)) {
return FALSE;
}
*type = (node.front)->type;
return TRUE;
}

1.6 出队

Status PopNode(StackNode *node,ElementType *type){
if (IsEmpty(*node)) {
return FALSE;
}
Chain *tabV = node->front;
*type = (node->front)->type;
(node->count)--;
if (node->count < 1) {
free(tabV);
node->front = NULL;
node->real = NULL;
}else{
node->front = tabV->next;
}
return TRUE;
}

1.7入队

Status PushNode(StackNode *node,int type){
if (NodeLength(*node)==MAXSIZE) {
printf("队已满");
return FALSE;
}
Chain *chain = (Chain *)malloc(sizeof(Chain));
chain->next = NULL;
chain->type = type;
if (node->count==0) {
node->front = chain;
node->real = chain;
}else{
node->real->next = chain;
node->real = chain;
}
(node->count)++;
return OK;
}

1.8 遍历 队列

Status TraverseNode(StackNode Node){
if (IsEmpty(Node)) {
printf("队列为空");
return FALSE;
}
Chain *chain = Node.front;
while (Node.count>0) {
printf("%d ",chain->type);
chain = chain->next;
Node.count--;
}
printf("\n");
return TRUE;
}

2.0 main 函数验证队列实现

int main(int argc, const char * argv[]) {
StackNode node;
InitNode(&node);
IsEmpty(node);
for (int i = 0; i<MAXSIZE; i++) {
PushNode(&node, i);
}
TraverseNode(node);
NodeLength(node);
ElementType ttt;
GetNodeHead(node, &ttt);
printf("head:%d \n",ttt);
for (int i = 0; i<10; i++) {
PopNode(&node, &ttt);
printf("type:%d \n",ttt);
NodeLength(node);
}
NodeLength(node);
TraverseNode(node);
BecomeEmpty(&node);
IsEmpty(node);
return 0;
}

算法面试题

 1 杨辉三角



模型如上图所示,基本可以理解为二维数组,

思路:1. 第一层循环控制行数i : 默认[i][0] = 1,[i][i] = 1

2. 第二层循环控制列数j : triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j]

代码实现

int **generate(int numRows,int *resturnSize){
*resturnSize = numRows;
int **res = (int **)malloc(sizeof(int*)*numRows);
for (int i = 0; i<numRows; i++) {
res[i] = (int *)malloc(sizeof(int)*(i+1));
res[i][0] = 1;
res[i][i] = 1;
for (int j = 1; j<i; j++) {
res[i][j] = res[i-1][j] + res[i-1][j-1];
}
}
return res;
}

int main(int argc, const char * argv[]) {
int numRows = 5;
int returnSize;
int **returnReslt;
returnReslt = generate(numRows, &returnSize);
for (int i = 0; i<returnSize; i++) {
printf("[");
for (int j = 0; j<=i; j++) {
printf(" %d",returnReslt[i][j]);
}
printf("]\n");
}
return 0;
}

2 爬楼梯



解法一:

/*
方法一:递归求解法
f(n) = f(n-1) + f(n-2);
f(1)=1;
f(2)=1;
*/
int ClimbStairs_1(int n){
if (n<1) {
return 0;
}
if (n == 1) {
return 1;
}
if (n==2) {
return 2;
}
return ClimbStairs_1(n-1) + ClimbStairs_1(n-2);
}

解法二:

/*
方法二:动态规划法
*/
int ClimbStairs(int n){
if (n==1) {
return 1;
}
int temp = n+1;
int *sum = (int *)malloc(sizeof(int)*temp);
sum[0] = 0;
sum[1] = 1;
sum[2] = 2;
for (int i = 3; i <= n ; i++) {
sum[i] = sum[i-1]+sum[i-2];
}
return sum[n];
}


3 每日气温

 题目: 根据每日气温列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置0来代替。例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

解题关键: 实际上就是找当前元素 从[i,TSize] 找到大于该元素时. 数了几次. 首先最后一个元素默认是0,因为它后面已经没有元素了.

/*
解法1:
1. 从左到右开始遍历,从第一个数到最后一个数开始遍历. 最后一个数因为后面没有元素,默认是0,不需要计算;
2. 从[i+1,TSize]遍历,每个数直到找到比它大的数,数的次数就是对应的值;
思路:
1.创建一个result 结果数组.
2.默认reslut[TSize-1] = 0;
3.从0个元素遍历到最后一个元素[0,TSize-1];
A.如果当前i >0 并且当前的元素和上一个元素相等,则没有必要继续循环. 则判断一下result[i-1]是否等于0,如果等于则直接将result[i] = 0,否则将result[i] = result[i-1]-1;
B.遍历元素[i+1,TSize]
如果当前T[j]>T[i],则result[i] = j-i;
如果当前T[j]已经是最后一个元素,则默认result[i] = 0;
*/
int *dailyTemperatures_1(int* T, int TSize, int* returnSize){
int *result = (int *)malloc(sizeof(int) * TSize);
*returnSize = TSize;
result[TSize-1] = 0;
for(int i = 0;i < TSize-1;i++)
if(i>0 && T[i] == T[i-1])
result[i] = result[i-1] == 0?0:result[i-1]-1;
else{
for (int j = i+1; j < TSize; j++) {
if(T[j] > T[i]){
result[i] = j-i;
break;
}
if (j == TSize-1) {
result[i] = 0;
}
}
}
return result;
}

/*

解法二:

1. 从右到左遍历. 因为最后一天的气温不会再升高,默认等于0;

2. i 从[TSize-2,0]; 从倒数第二天开始遍历比较. 每次减一;

3. j 从[i+1,TSize]遍历, j+=result[j],可以利用已经有结果的位置进行跳跃,从而减少遍历次数

-若T[i]<T[j],那么Result = j - i;

-若reuslt[j] == 0,则表示后面不会有更大的值,那么当前值就应该也是0;

思路:

1.创建一个result 结果数组.

2.默认reslut[TSize-1] = 0;

3.从TSize-2个元素遍历到第一个元素[TSize-2,0];

4.从[i+1,TSize]遍历,j+=result[j];

-若T[i]<T[j],那么Result = j - i;

-若reuslt[j] == 0,则表示后面不会有更大的值,那么当前值就应该也是0;

*/

int *dailyTemperatures_2(int* T, int TSize, int* returnSize){
int *result = (int *)malloc(sizeof(int) * TSize);
*returnSize = TSize;
result[TSize-1] = 0;
for (int i=TSize-2; i >= 0; i--) {
for (int j = i+1; j < TSize; j+=result[j]) {
if (T[i] < T[j]) {
result[i] = j-i;
break;
}else
{
if (result[j] == 0) {
result[i] = 0;
break;
}
}
}
}
return result;
}

main函数验证:

int main(int argc, const char * argv[]) {
printf("每日温度问题!\n");
int test[10]= {5,7,8,2};
//int test[10]= {73, 74, 75, 71, 69, 72, 76, 73};

int *result;
int returnSize;
 result = dailyTemperatures_1(test, 8, &returnSize);
//result = dailyTemperatures_2(test, 8, &returnSize);
printf("\n");

for (int i = 0; i < returnSize;i++ ) {
printf("%d ",result[i]);
}
return 0;
}

4 括号匹配检验

题目:

假设表达式中允许包含两种括号:圆括号与⽅括号,其嵌套顺序随意,即([]()) 或者[([][])]都是正

确的.⽽这[(]或者(()])或者([()) 都是不正确的格式. 检验括号是否匹配的⽅法可⽤
.例如,考虑以下括号的判断: [ ( [ ] [ ] ) ] 

分析:这个可以理解为栈结构,陷入后出,后出先入,[ ,( 可以理解为入栈元素;],)这两个可以理解为出栈元素,用栈概念可以完美验证该类字符串

代码:

#define Stack_Init_Size 100#define Stack_increment 10//栈的定义typedef struct {    char *base;//栈底指针    char *top;//栈顶指针    int stacksize;}SqStack;
int Init(SqStack *stack){    stack->base = (char *)malloc(sizeof(char)*Stack_Init_Size);    stack->top = stack->base;    if (stack->top) {        return -1;    }    stack->stacksize = Stack_Init_Size;    printf("初始化成功");    return 0;}
//获取栈顶数据char GetTop(SqStack stack){    if (stack.base == stack.top) {        //printf("栈中没有数据");        return '#';    }    return *(stack.top-1);}

//往栈栈中插入元素int Push(SqStack *stack,char element){    if (stack->top-stack->base == stack->stacksize) {        stack->base = (char *)realloc(stack->base, Stack_increment*sizeof(char));        stack->top = stack->base + stack->stacksize;        stack->stacksize += Stack_increment;    }    *stack->top = element;    stack->top += 1;    return 0;}//元素出栈char Pop(SqStack *stack){    if (stack->top == stack->base) {        printf("栈为空\n");    return '#';    }    return *--stack->top;}
//释放栈空间int Destroy(SqStack *stack){    free(stack->base);    stack->stacksize=0;    return 0;}//栈数据处理
int ExecuteData(SqStack stack,char* data){    Push(&stack,data[0]);    for(int i=1;i<strlen(data);i++){        char top = GetTop(stack);        switch(top){            case '(':                if(data[i]==')')Pop(&stack);                else Push(&stack,data[i]);                break;            case '[':                if(data[i]==']')Pop(&stack);                else Push(&stack,data[i]);                break;            case '#':                if(data[i]=='('||data[i]=='['){                    Push(&stack,data[i]);                    break;                }                else                    default:return -1;break;        }    }    //如果栈为空,则返回"0"->匹配成功 否则返回"-1"匹配失败    if(stack.top==stack.base){        Destroy(&stack);        return 0;    }    else{        Destroy(&stack);        return -1;    }}

int main(){    SqStack stack;    Init(&stack);    char data[180];    scanf("%s",data);    int result = ExecuteData(stack,data);    if(result==0)printf("括号是正确匹配的\n");    else printf("括号匹配不正确\n");    return 0;}