数据结构----结构--线性结构--栈,队列

数据结构----结构–线性结构–栈,队列

一.栈:Stack

1.栈的特点:

​ 先进后出:FILO(对一组数据有倒叙要求时可以用栈)

2.栈的实现

顺序存储:数组实现:

​ 缺点:空间大小受限

链式存储:链表实现

3.栈的基本函数(这里是一部分)

1.Init

2.Push

3.Pop

4.Clear

5.Destory

6.Count

7.IsEmpty

创建栈,并实现Push,Pop这两个函数

代码如下

//c语言
#include 
#include 
typedef struct Node { 
	int m_value;
	struct Node* m_pNext;

}PNode;

PNode* creatStack() {//创建栈
	PNode* stackTop = NULL;//栈顶
	return stackTop;
}
void  creatStackNode(int x, PNode** stackTop) {//创建栈中的元素
    PNode* Temp = (PNode*)malloc(sizeof(PNode));
    Temp->m_value = x;
    Temp->m_pNext = NULL;

	//添加元素
	Temp->m_pNext = *stackTop;
    *stackTop = Temp;
}

void stackpush(int x, PNode** stackTop) {//往栈里添加元素
	creatStackNode(x, stackTop);//创建元素,并添加元素
}

void stackpop(PNode** stackTop) {//出栈
	if (stackTop == NULL) return;
	PNode* Temp = *stackTop;
	printf("%d\n", Temp->m_value);//输出该元素的值
	*stackTop = (*stackTop)->m_pNext;
	free(Temp);//释放空间
}



int main() {
	PNode* stackTop = creatStack();//获得一个栈,此时是空栈

	stackpush(3, &stackTop);//添加元素
	stackpush(6, &stackTop);
	stackpush(7, &stackTop);

	stackpop(&stackTop);//弹出元素
	stackpop(&stackTop);
	stackpop(&stackTop);

	return 0;
}

进行所有函数的实现(对上面代码进行一些改动)

代码如下

//c语言
#include 
#include 
typedef struct Node {
	int m_value;
	struct Node* m_pNext;

}PNode;

typedef struct Top {
	PNode* p_Top;
	int count;
}PTop;


PTop* Init() {//创建
	PTop* p1 = (PTop*)malloc(sizeof(Top));
	p1->p_Top = NULL;
	p1->count = 0;
	return p1;
}
void  creatStackNode(int x, PTop* P_Top) {//创建栈中的元素
	if (P_Top == NULL) {
		printf("栈不存在\n");
		exit(1);
	}
	PNode* Temp = (PNode*)malloc(sizeof(PNode));
	Temp->m_value = x;
	Temp->m_pNext = NULL;
	//添加元素
	printf("入栈元素的值为%d\n", Temp->m_value);
	Temp->m_pNext = P_Top->p_Top;
	P_Top->p_Top = Temp;
	P_Top->count += 1;
}

void stackpush(int x, PTop* P_Top) {//往栈里添加元素
	creatStackNode(x, P_Top);//创建元素,并添加元素
}

void stackpop(PTop* P_Top) {//出栈
	if (P_Top->p_Top == NULL) return;
	PNode* Temp = P_Top->p_Top;
	printf("出栈元素的值为%d\n", Temp->m_value);//输出该元素的值
	P_Top->p_Top = (P_Top->p_Top)->m_pNext;
	P_Top->count -= 1;
	free(Temp);//释放空间
}

void clear(PTop* P_Top) {//清空栈
	if (P_Top->count == 0) {
		printf("无链表\n");
	}
	while (P_Top->p_Top != NULL) {
		stackpop(P_Top);
	}
	printf("链表已被清空\n");
}

void Count(PTop* P_Top) {//看栈中的元素有几个
	printf("栈中的元素有%d个\n",P_Top->count);
}

int IsEmpty(PTop* P_Top) {//判断是否为空
	if (P_Top->count) {
		printf("不为空 返回\n");
		return 1;
	}
	else {
		printf("为空 返回\n");
		return 0;
	}
}
void GetTop(PTop* P_Top) {
	printf("栈顶元素为");
	printf("%d\n",(*P_Top->p_Top).m_value);
}

void Destory(PTop** P_Top) {
	if (P_Top == NULL) {
		printf("无栈");
	}
	clear(*P_Top);
	printf("栈顶已被回收\n");
	delete *P_Top;
	*P_Top = NULL;
}
int main() {
	PTop* P_Top = Init();//获得栈顶

	stackpush(3, P_Top);//添加元素
	stackpush(6, P_Top);
	GetTop(P_Top);
	Count(P_Top);
	stackpush(7, P_Top);

	Destory(&P_Top);
	//stackpop(&P_Top);//弹出元素
	//stackpop(&P_Top);
	//stackpop(&P_Top);
	stackpush(3, P_Top);
	return 0;
}

4.可用栈的题目

第一题

题目:一万个括号 ‘(’ ‘)’,判断这些括号是否完全匹配
解决
方法一:

​ 1.循环,如果是左括号就入栈

​ 2.如果是右括号将栈顶的元素出栈,如果栈中无元素,就是不匹配,右括号无对应的左括号

​ 3.当括号都处理完了,那么循环结束,可以判断完全匹配

方法二:

​ 循环,左半括号记为加1,右半括号记为-1,当总和小于0时就是不匹配

​ 当括号都处理完了,那么循环结束,可以判断完全匹配

第二题(网址为https://leetcode.cn/problems/valid-parentheses/)

题目:给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。
解决

​ 1.循环,如果是左括号就入栈

​ 2.如果是右括号将栈顶的元素出栈,并根据出栈的括号类型进行判断,如果栈中无元素,就是不匹配,右括号无对应的左括号

​ 3.当括号都处理完了,那么循环结束,可以判断完全匹配

代码如下
//这里的代码是c++语言下的
class Solution {
public:
    bool isValid(string s) {
        stack sta;//创建一个栈
        const char* temp=s.c_str();//遍历字符串的变量
        while(*temp!='\0'){//遍历
            if(*temp=='('||*temp=='{'||*temp=='['){//如果字符为左括号就入栈
                sta.push(*temp);
            }
            else{
                
                if(sta.empty()){//如果有右括号,没有左括号了,不闭合,失败
                    return false;
                }
                if(sta.top()=='('){//右括号与左括号不匹配,不闭合,失败
                    if(*temp!=')'){
                        return false;
                    }
                }
                else if(sta.top()=='{'){
                    if(*temp!='}'){
                        return false;
                    }
                }
                else if(sta.top()=='['){
                    if(*temp!=']'){
                        return false;
                    }
                }
                sta.pop(); 
            }
            temp+=1;
        }
        if(!sta.empty()){
            return false;
        }
        return true;
    }
};

5.递归时间复杂度的计算

主方法求解递归式:T(n)=aT(n/b)+f(n) (n代表要处理数据的规模,T代表处理这个数据规模的时间消耗,a时子问题的个数,b分之n代表当前子问题处理的数据规模式原有数据量的几分之几,f(n)时除了递归以外要做的事情所用的时间消耗)

计算:比较nlogb的a次方和f(n),谁大谁就是递归的时间复杂度

​ 一样大的话,nlogb的a次方乘以log2的n次方就是递归的时间复杂度

6.计算器运算(应用栈)

1.中缀表达式(简称为表达式)

2.后缀表达式

3.中缀转后缀:

​ 1.借助辅助线

​ 2.遇到数字或字母,直接输出

​ 3.遇到符号,将当前符号与栈顶元素进行优先级比较

​ (1)当前符号优先级高,入栈

​ (2)当前符号优先级没有栈顶符号优先级高,栈内元素依次出栈,直到比当前元素优先级低为止,再将当前元素入栈

​ 4.遇到“(”无条件入栈,遇到")“栈内元素依次出栈,直到”)"停止

快速转换:把每个运算式都加上括号,括号里的运算符号都移到右括号外

4.后缀转前缀:

​ 1.借助辅助栈

​ 2.遇到数字或字母直接入栈

​ 3.遇到符号,将栈顶元素的下一个和栈顶元素构成表达式

二.队列:queue

1.队列的特点:

​ 先进先出:FIFO

2.队列的实现

顺序存储:数组实现:

​ 缺点:空间大小受限

​ 日和实现循环队列:进行取余 取余的是数组的长度

链式存储:链表实现

3.队列的基本函数(这里是一部分)

1.Init

2.Push

3.Pop

4.front

5.empty

将这里所有的函数功能进行实现

代码如下

#include 
#include
typedef struct node {
	int m_value;
	struct node* m_next;
}NODE;

typedef struct node2 {
	int count;
	NODE* m_head;
	NODE* m_tail;
}P_POINT;


//队列初始化
void init(P_POINT** point) {
	*point = (P_POINT*)malloc(sizeof(P_POINT));
	(*point)->count = 0;
	(*point)->m_head = NULL;
	(*point)->m_tail = NULL;
}

//添加元素
void Push(P_POINT* point,int x) {
	if (point == NULL) return;
	NODE* Temp = (NODE*)malloc(sizeof(NODE));//创造节点
	Temp->m_value = x;//初始化
	Temp->m_next = NULL;
	if (point->m_head == NULL) {//头节点如果为空
		point->m_head = Temp;
		point->m_tail = Temp;
		printf("添加的元素为%d\n", Temp->m_value);
	}
	else {//头节点不为空
		point->m_tail->m_next = Temp;
		point->m_tail = Temp;
		printf("添加的元素为%d\n", Temp->m_value);
	}
	point->count += 1;
}

//删除队头
void pop(P_POINT* point) {
	if (point == NULL) return;
	if (point->count == 0) return;

	NODE* Temp = point->m_head;
	point->m_head = point->m_head->m_next;
	printf("删除的元素为%d\n", Temp->m_value);
	free(Temp);
	point->count -= 1;
	if (point->count == 0) {
		point->m_tail = NULL;
	}
}

//获得队头
void GetFront(P_POINT* point) {
	printf("队首为%d\n", point->m_head->m_value);
}

//获得队列长度
void GetCount(P_POINT* point) {
	printf("获得队列的长度为%d\n",point->count);
}

//判断队列是否为空
void IsEmpty(P_POINT* point) {
	if (point->count != 0) {
		printf("队列不为空\n");
	}
	else {
		printf("队列为空\n");
	}
}


int main() {
	P_POINT* point = NULL;
	init(&point);//队列初始化
	Push(point, 5);//放入元素
	Push(point, 7);
	Push(point, 8);
	GetCount(point);//得到队列中元素的个数
	Push(point, 1);
	GetFront(point);//得到队头元素
	pop(point);//删除队列中的元素
	pop(point);
	pop(point);
	IsEmpty(point);//k
	return 0;
}

三.两个栈实现队列

实现:

​ 1.第一个栈进行入队,第二个栈进行出队

​ 2.当进行入队时,如果第二个栈中有元素,将第二个栈中的元素出栈并添加到第一个栈中,在第一个栈中添加新的元素

​ 3.当进行出队时,如果第一个栈中有元素,将第一个栈中的元素出栈并添加到第二个栈中,在第二个栈中进行弹出操作

两个栈实现队列的题(网址为https://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/)

题目:

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTaildeleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

代码如下:

//这里的代码是c++语言下的
class CQueue {
public:
    CQueue() {

    }
    stack sta1;
    stack sta2;
    void appendTail(int value) {//添加元素
        while(!sta2.empty()){
            int temp=sta2.top();
            sta1.push(temp);
            sta2.pop();
        }
        sta1.push(value);
    }
    
    int deleteHead() {//删除元素
        while(!sta1.empty()){
            int temp=sta1.top();
             sta2.push(temp);
             sta1.pop();
        }
        if(sta2.empty()){
            return -1;
        }
        int temp2=sta2.top();
        sta2.pop();
        return temp2;
    }
};

四.两个队列实现栈

实现:

1.入栈:新元素添加到非空的队列中(第一次两个队列都为空,添加到哪个里面都可以)

2.出栈:将非空的队列中的元素除尾元素外都添加到另一个空队列里,然后将尾部的那个元素删除

用两个队列实现栈的题(网址为https://leetcode.cn/problems/implement-stack-using-queues/)

题目:

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppopempty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false

注意:

  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsizeis empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

代码如下:

//这里的代码是c++语言下的
class MyStack {
public:
    MyStack() {

    }
    queue q1;
    queue q2;
    int bool1=1;
    void push(int x) {//添加元素
        if(bool1){
            q1.push(x);
            bool1=0;
        }
        else{
             if(!q1.empty()){
            q1.push(x);
        }
        else{
            q2.push(x);
        }
        }
 }
    
    int pop() {//移除并返回移除元素
        int temp=0;
        if(!q1.empty()){
            while(q1.size()>1){
                    q2.push(q1.front());
                    q1.pop();
                }
                temp=q1.front();
                q1.pop();
        }
        else{
            while(q2.size()>1){
                    q1.push(q2.front());
                    q2.pop();
                }
                temp=q2.front();
                q2.pop();
        }
       
        return temp;   
    }
    
    int top() {//获得栈顶元素
         int temp=0;
        if(!q1.empty()){
            while(q1.size()>1){
                    q2.push(q1.front());
                    q1.pop();
                }
                temp=q1.front();
                q2.push(q1.front());
                q1.pop();
            }
         else{
            while(q2.size()>1){
                    q1.push(q2.front());
                    q2.pop();
                }
                temp=q2.front();
                q1.push(q2.front());
                q2.pop();
         }
           return temp;
    }
    
    bool empty() {
        if(q1.empty()&&q2.empty()){
            return true;
        }
        return false;
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

你可能感兴趣的:(数据结构,数据结构)