【データ構造とアルゴリズム】 スタックを理解し、スタックに関連する機能を実現する

ここまで、線形テーブルの概念、動的および静的シーケンス テーブルの確立、および 2 つのリンク リストの実現を理解して理解しました。次に、新しいコンテンツ、新しい概念であるスタックを知る必要があります。シーケンス テーブルまたはリンク リストに基づく新しいタイプのデータ構造。

目次

1. スタックとは何ですか?

2 番目に、スタックの実装

1. 実現方法

2.スタックの機能を実装する

1.スタックを初期化する

2. スタックにプッシュします

3. 飛び出す

4. スタックの最上位要素を表示する

5. 印刷スタックと空スタック

3. 完全なコード実装

1. リンクリスト実装スタック

2. 配列(シーケンステーブル)はスタックを実装します

要約する


1. スタックとは何ですか?

スタック: 特別な線形リストです。1 つの固定端でのみ挿入と削除が可能です。データが挿入および削除される端をスタックの最上位と呼び、もう一方の端をスタックの最下位と呼びます。スタック内のデータ要素は、先入れ後出し (後入れ先出し) の原則に従います。

以前C言語を勉強していた時に、2つの概念を聞きました。

1. スタックのプッシュ: スタックの挿入操作はプッシュ、プッシュ、プッシュなどと呼ばれ、挿入されたデータはスタックの先頭にあります。

2. ポッピング:スタックの削除操作をポッピングと呼びます。出力データもスタックの最上位にあります

 

2 番目に、スタックの実装

1. 実現方法

二つあります

1. 末尾挿入、末尾削除のコストが低く、スタック内の指定要素が変更、削除されてもただ移動するだけなので、シーケンステーブルの形で実装できます。


写真が示すように:

構造体コードは以下のとおりです。

#define MAX 100
#define CAp 4 ///初始化的时候capacity的容量
#define Make 2//每一次增加的newCapacity的容量
//静态
typedef struct Stacknode {
	int data[MAX];//数据域
	int size;//表示元素个数
}Stack;
//动态
typedef struct Stacknode2 {
	int* data;//数据域
	int size;//表示元素个数
	int capacity;//表示当前容量
}Stack1;

2. スタック テーブルをリンク リスト形式で実装します。

構造は次のとおりです。

//创建基础结构
typedef struct node {
	int data;
	struct node* next;
}ST;


//栈实际上就是一个只能进行头插头删的单向链表
//创建栈的头尾结点 结构体
typedef struct stack {
	struct node* top;//栈顶元素地址
	struct node* bottom;//栈底元素地址
	int size;//栈的元素个数
};

2.スタックの機能を実装する

リンク リスト実装スタックを例として、配列を使用してスタックを実装するための完全なコードをこの記事の最後にまとめます。

1.スタックを初期化する

上記の構造タイプを使用すると、構造は上記のようになります

コードは以下のように表示されます:


//初始化栈
struct stack* create_stack()
{
	struct stack* s = (struct stack*)malloc(sizeof(struct stack));
	s->size = 0;
	s->bottom = s->top = NULL;
	return s;
}

malloc 関数を使用してスペースを適用し、 s のサイズを 0 に設定します。bottom と top は、スタックの底部とスタックの上部が NULL を指すことを示します。

2. スタックにプッシュします

写真が示すように:

 コードは以下のように表示されます:

//创建新的结点
struct node* create_node(int data) {
	struct node* newnode = (struct node*)malloc(sizeof(struct node));
	newnode->next = NULL;
	newnode->data = data;
	return newnode;
}

//入栈
//入栈首先要将准备入栈的元素封装成结点,和链表没有差别

void stackPush(struct stack* s, int x) {
	ST* newnode = create_node(x);
	newnode->next = s->top;
	s->top = newnode;
	s->size++;
}

3. 飛び出す

写真が示すように:

コードは以下のように表示されます:

//出栈
void stackPop(struct stack* s, int* x) {
//判断是否为空栈   如果是 空栈的话就  使得输出 Pop failed
	if (s->size == 0) {
		printf("Pop failed\n");
		exit(-1);
	
	}
	//创建结点临时变量  赋值得到栈顶元素
	ST* tmp = s->top;
	*x = tmp->data;//得到数值
	s->top = tmp->next;
	s->size--;
}

4. スタックの最上位要素を表示する

コードは以下のように表示されます:

//查看栈顶元素
void stackTop(struct stack* s, int* x) {
	if (s->size == 0) {
		printf("空栈~~\n");
		exit(-1);
	}

	*x = s->top->next->data;
}

5. 印刷スタックと空スタック

コードは以下のように表示されます:

//清空栈
void make_stack_empty(struct stack* s) {
	s->size = 0;
	s->bottom = s->top ;
	//将栈底等于栈顶就可以  然后将size为0

}
void stackPrint(struct stack* s) {
	//打印栈表
	ST* list = s->top;
	printf("top -> ");
	while (list!=NULL) {
		printf("%d -> ", list->data);
		list = list->next;
	}
}

3. 完全なコード実装

1. リンクリスト実装スタック

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>

//创建基础结构
typedef struct node {
	int data;
	struct node* next;
}ST;


//栈实际上就是一个只能进行头插头删的单向链表
//创建栈的头尾结点 结构体
typedef struct stack {
	struct node* top;//栈顶元素地址
	struct node* bottom;//栈底元素地址
	int size;//栈的元素个数
};
//表示每一个栈都是struct stack* 类型的,栈中的每一个怨怒是都是struct node *类型的  不仅需要为栈分配内存,还需要为压入栈中的元素分配内存

/*
node中的next指针用于让栈中上面的节点连接到下面的节点,stack中的top和bottom分别存放当前栈顶元素的地址和栈底元素的后一个位置的地址(NULL),
因为是用于指向栈中节点的指针,所以得是struct node* 类型。*/

//初始化栈
struct stack* create_stack()
{
	struct stack* s = (struct stack*)malloc(sizeof(struct stack));
	s->size = 0;
	s->bottom = s->top = NULL;
	return s;
}

//一开始栈是空的所以 size为0  top  bottom是NULL

//创建新的结点
struct node* create_node(int data) {
	struct node* newnode = (struct node*)malloc(sizeof(struct node));
	newnode->next = NULL;
	newnode->data = data;
	return newnode;
}

//入栈
//入栈首先要将准备入栈的元素封装成结点,和链表没有差别

void stackPush(struct stack* s, int x) {
	ST* newnode = create_node(x);
	newnode->next = s->top;
	s->top = newnode;
	s->size++;
}

//出栈
void stackPop(struct stack* s, int* x) {
//判断是否为空栈   如果是 空栈的话就  使得输出 Pop failed
	if (s->size == 0) {
		printf("Pop failed\n");
		exit(-1);
	
	}
	//创建结点临时变量  赋值得到栈顶元素
	ST* tmp = s->top;
	*x = tmp->data;//得到数值
	s->top = tmp->next;
	s->size--;
}

//查看栈顶元素
void stackTop(struct stack* s, int* x) {
	if (s->size == 0) {
		printf("空栈~~\n");
		exit(-1);
	}

	*x = s->top->next->data;
}

//清空栈
void make_stack_empty(struct stack* s) {
	s->size = 0;
	s->bottom = s->top ;
	//将栈底等于栈顶就可以  然后将size为0

}
void stackPrint(struct stack* s) {
	//打印栈表
	ST* list = s->top;
	printf("top -> ");
	while (list!=NULL) {
		printf("%d -> ", list->data);
		list = list->next;
	}
}
int main()
{
	struct stack *s = create_stack();
	stackPush(s, 1);
	stackPush(s, 2);
	stackPush(s, 3);
	stackPush(s, 4);
	stackPush(s, 5);
	stackPrint(s);
	int a = 0;
	stackPop(s,&a);
	printf("\n%d\n", a);
	stackPrint(s);
	return 0;
}

2. 配列(シーケンステーブル)はスタックを実装します

#define _CRT_SECURE_NO_WARNINGS
#include"steck.h"
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
//栈是限定在一个表里面的一段进行插入删除操作的线性表
// 数据进出的顺序为先进后处
// 应用场景:网页浏览的时候的后退  编辑软件的撤销
// 
//创建栈  两个方式:数组(顺序表)和 单链表


//1.数组:选用数组用来做栈的存储结构,只需要在数组末尾进行操作即可,完美避开数组操作中挪动数据缺陷
      //   显然是可以用数组来做栈的存储结构
//2.单链表  :因为栈是吸纳星表的一段进行操作,所以一般是用链表头进行操作

//进行头插头删  是用链表更好 效率更高


//1.用数组的方式
typedef int StackDataType;
typedef struct Stcak {
    StackDataType* data;
    int top;
    int capacity;   //数据域和元素个数
}ST;

//初始化
void StackInit(ST* ps) {
    ps->data = (StackDataType*)malloc(sizeof(StackDataType) * 4);
    if (ps->data == NULL) {
        printf("malloc failed\n");
        exit(-1);
    }
    ps->top = 0;
    ps->capacity = 4;

}
//压栈
void StackPush(ST* ps, int x) {
    assert(ps);//断言
    //满了就扩容
    if (ps->top == ps->capacity) {
        StackDataType* tmp = (StackDataType*)realloc(ps->data, sizeof(StackDataType) * ps->capacity * 2);
        if (tmp == NULL) {
            printf("realloc failed\n");
            exit(-1);
        }
        else {
            ps->data = tmp;
            ps->capacity *= 2;

        }
    }
    ps->data[ps->top] = x;
    ps->top++;

}
//出栈
void StackPop(ST* ps) {
    //出栈是将最后一个元素放出来  先进后出
    assert(ps);
    assert(ps->top > 0);//断言进行判断是否栈为空  即top!=0
    ps->top--;
    //直接减减就可以  没有了对应元素 的数据  如果再次压栈的话 会把之前的数据进行更改
}

//取得栈顶元素
StackDataType StackTop(ST* ps) {
    assert(ps);
    assert(ps->top > 0);
    return ps->data[ps->top - 1];//因为top栈顶始终要保持比元素个数大一,保证压栈的时候先压栈然后再加加
//所以取栈顶元素 的时候 top-1
}

//销毁栈
void StackDestory(ST* ps) {
    assert(ps);
    free(ps->data);
    //释放数组data的空间
    ps->data = NULL;
    ps->top = ps->capacity = 0;

}

//求栈中元素个数
int StackSize(ST* ps) {
    assert(ps);
    return ps->top;
}
//判断是否为空
bool StackEmpty(ST* ps) {
    assert(ps);
    return ps->top == 0;
}
void StackPrint(ST* ps) {
    //打印栈表
    assert(ps);
    for (int i = 0; i < ps->top; i++) {
        printf("%d ", ps->data[i]);
    }
    printf("\n");
}
int main()
{
    ST s;
    ST *ps=&s;
  /*  StackInit(&ps);
    StackPush(&ps, 1);
    StackPush(&ps, 2);
    StackPush(&ps, 3);
    StackPush(&ps, 4);
    StackPush(&ps, 5);
    StackPrint(&ps);*/
    StackInit(ps);
    StackPush(ps, 1);
    StackPush(ps, 2);
    StackPush(ps, 3);
    StackPush(ps, 4);
    StackPush(ps, 5);
    StackPop(ps);//出栈成功
    StackPrint(ps);
    printf("%d \n", StackTop(ps));//取得栈顶元素
    printf("%d \n", StackSize(ps));//获得栈表元素个数
    StackDestory(ps);
    StackPrint(ps);//销毁栈表成功
    return 0;
}

要約する

スタックはテーブル内のセクションに限定された線形テーブルであり、そのテーブルに対して挿入および削除操作が実行されます データの入力と終了の順序は最初と最後です 適用シナリオ: Web ページを閲覧するとき、裏編集ソフトウェア実際、スタックの機能は次のようなもので、シーケンス テーブルとリンク リストの使用法を学び、スタックについては、ヘッドをワイプして削除する方法を知っていれば、概念を理解し、習得して実装するのは簡単です。スタック。

次に、スタックに似ていますが異なるキューについて説明します。ご期待ください。サポートありがとうございました。

おすすめ

転載: blog.csdn.net/qq_63319459/article/details/128793244