Data Structure and Algorithm Fundamentals (Wang Zhuo) (11): Definition of stack and its basic operations (sequence and chain initialization, length finding, whether it is empty, clearing and destroying, popping and pushing), stack and recursion

Table of contents

 Definition of stack:

Design references for sequential stacks and chain stacks:

Sequential stack:

Preconditions:

initialization:

Simple operation: (find the length, whether it is empty, empty and destroy)

empty:

destroy:

Push stack:

Pop:

Chain stack:

Preconditions:

Simple operation: (initialization, whether it is empty, taking the top element of the stack)

Into the stack:

Pop:

stack and recursion

Tail recursion → loop structure

One-way recursion → loop structure


 Definition of stack:

stack : a pile, a pile; pile; stack;


Design references for sequential stacks and chain stacks:

Fundamentals of Data Structure and Algorithm (Wang Zhuo) (7): Summary: Definition and Operation of Linked List and Linear List_宇-Yu's Blog-CSDN Blog


Sequential stack:


Preconditions:

(Here is the construction form of linear list, and it can also be written as the construction form of linked list)

//基于线性表的定义所做的更改
#include<iostream>
using namespace std;
#include<stdlib.h>//存放exit
#include<math.h>//OVERFLOW,exit

#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE  -1
//#define OVERFLOW   -2   

#define MAXlength 100  
//可按需修改,PPT中写的是MAXlength

struct Poly
{
	float p;
	int e;

	bool operator==(Poly t)
	{
		return t.p == p && t.e == e;
	}
	bool operator!=(Poly t)
	{
		return t.p != p || t.e != e;
	}
};

struct Sqlist
{
	Poly* elem;
	int length;
};

typedef int Status; 
typedef Poly Elemtype;
typedef Elemtype SElemType;
//注意:这一段必须写在调用SElemType类型及其指针之前

struct SqStack
{
	SElemType* base; //栈底指针  
	SElemType* top;//栈顶指针
	int stacksize; //栈可用最大容量
};

initialization:

Status InitStack(SqStack& S)//构造一个空栈
{
	S.base = new SElemType[MAXlength];
	//或
	//S.base = (SElemType*)malloc(MAXlength * sizeof(SElemType));
	if (!S.base) exit(OVERFLOW);// 存储分配失败
	S.top = S.base;
	//栈顶指针等于栈底指针
	S.stacksize = MAXlength;
	return true;
}

Simple operation: (find the length, whether it is empty, empty and destroy)

Status StackEmpty(SqStack S)
{
	// 若栈为空,返回TRUE;否则返回FALSE 
	if (S.top == S.base)
		return TRUE;
	else
		return FALSE;
}

int StackLength(SqStack S)
{
	return S.top - S.base;
}

Status ClearStack(SqStack S)//清空顺序栈
{
	if (S.base)
		S.top = S.base;
	return OK;
}


Status DestroyStack(SqStack& S)//销毁
{
	if (S.base)
	{
		delete S.base;
		S.stacksize = 0;
		S.base = S.top = NULL;
	}
	return OK;
}

Here, we can easily have such questions:

Regarding emptying and destruction, shouldn't we set the elements to NULL one by one? ? ?

The destruction and clearing here only change the value of the pointer pointing to this location, but the content of the location is not empty (null)? ?

The actual reason is explained as follows:

empty:


Here we actually just let (return) the stack to (put) the state of an empty stack (the two pointers point to the same stack point)

As for the contents of the stack, it doesn't matter whether it is cleared or not:

Because as long as we write elements later, the elements that have not been eliminated in the stack before will naturally be overwritten


destroy:


Destroy the base pointer directly, here we may feel:

You are just destroying the base pointer. Why do you say that we can destroy the contents and memory of the entire stack by doing this?

In fact, he did. As for the reason, we can look at the initialization operation of the table:

When initializing the table, the operation we adopt is to open up memory space for the base pointer:

    S.base = new SElemType[MAXlength];

So as long as we destroy the base pointer, we can realize the operation of destroying the contents and memory of the entire stack:

The delete operation destroys the content inside the base pointer and also destroys the memory space of the entire stack with the base pointer as the head pointer


Push stack:

Program design process:


program:

Status Push(SqStack& S, SElemType e)
{
	if (S.top-S.base==S.stacksize)//不是MAXlength
		return OVERFLOW;
	*S.top = e;
	S.top++;
	//也可以写成:
	//*S.top++ = e;
	return true;
}

ISSUES:


(1):

Note that the statement where the stack is full here is:

    if (S.top-S.base==S.stacksize)

Among them, S.stacksize cannot write MAXlength


(2):

Regarding the precedence issue with *S.top++ = e; :

Increment (arithmetic operator) has precedence over assignment operator

So in theory, here should be self-increment first, then operation

But (however), here we write the statement using: *S.top++

That is to say: wait until all other operations in the statement are executed, and then perform the self-increment operation

So it is equivalent to assigning a value first and then increasing it


Pop:

Program design process:


program:

Status Pop(SqStack& S, SElemType& e)
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;	否则返回ERROR
{
	if (S.top == S.base) // 等价于 if(StackEmpty(S))
		return UNDERFLOW;//ERROR;
	e = *S.top;
	S.top--;
	//e = *--S.top;
	return true;
}

Similarly, here the value is assigned first, and then decremented;

I won't repeat it here


Chain stack:

Preconditions:

//基于链表的定义所做的更改
#include<iostream>
using namespace std;
#include<stdlib.h>//存放exit

#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE  -1
//#define OVERFLOW   -2   

#define MAXlength 100  //初始大小为100,可按需修改

struct K//Poly
{
    float a;
    int b;
    string c;
    bool operator==(K& t)
    {
        return t.a == a && t.b == b;
        //&& t.c = c;
    }
    bool operator!=(K& t)
    {
        return t.a != a || t.b != b;
        //|| t.c = c;
    }
};
typedef K Elemtype;         //函数调用状态

struct Lnode
    //node:结; 结点;
{
    Elemtype data;
    Lnode* next;
};
typedef Lnode* LinkList;

typedef int Status; 
typedef K Elemtype;
typedef Elemtype SElemType;
//注意:这一段必须写在调用SElemType类型及其指针之前

struct StackNode
{
    SElemType data;
    StackNode* next;
};
typedef StackNode *LinkStack;
LinkStack S;

Among them: (module structure analysis) 

SElemType: Poly (composite) type

top, base: SElemType type pointer

 In addition, we need to pay attention here that when defining a structure, it is possible to nest itself (recursion) , which is essentially like:

#include<iostream>
using namespace std;

struct S
{
    int data;
    S* next;
};

int main()
{

}

Simple operation: (initialization, whether it is empty, taking the top element of the stack)

int InitStack(LinkStack& S) 
{
    //构造一个空栈,栈顶指针置为空
    S = NULL;
    return OK;
}

Status StackEmpty(LinkStack S)
{
    if (S == NULL)
        return TRUE;
    else return FALSE;
}

SElemType GetTop(LinkStack S)
{
    if (S != NULL)
        return S->data;
}


Into the stack:

Status Push(LinkStack& S, SElemType e)
{
    StackNode* p = new StackNode;
    p->data = e;
    p->next = S;

    S = p;

    return true;
}

Pop:


I write:

Status Pop(LinkStack& S, SElemType e)
{
    LinkStack p = S;
    e = p->data;
    S = p->next;
    delete p;
    return true;
}

Referring to the PPT, we can find that it would be better and more rigorous to make the following changes:

Add statement:
    if (S == NULL) return ERROR;

 

The returned e is a reference type

final version:

Status Pop(LinkStack& S, SElemType &e)
{
    if (S == NULL) return ERROR;
    LinkStack p = S;
    e = p->data;
    S = p->next;
    delete p;
    return true;
}

stack and recursion


Tail recursion → loop structure

long Fact(long n)
{
    if (n == 0) return 1;
    else 
        return n * Fact(n - 1);
}

Change

long Fact(long n)
{
    auto t = 1;
    for (auto i = 1; i <= n; i++)
        t = t * i;

        return t;
}


One-way recursion → loop structure

long Fib(long n) // Fibonacci数列
{
    if (n == 1 || n == 2)
        return 1;
    else return
        Fib(n - 1) + Fib(n - 2);
}


Change


long Fib(long n) 
{
    if (n == 1 || n == 2)
        return 1;
    else 
    {
        int t1 = 1,t2 = 1;
        for(int i = 3; i <= n; i++)
        {
            int t3 = t1 + t2;
            t1 = t2; t2 = t3;
                return t3;
        }

    }

Guess you like

Origin blog.csdn.net/Zz_zzzzzzz__/article/details/128790962