基于C语言的数据结构_栈 学习笔记

目录

前言

00数据结构开篇

01栈的实现原理

01.1 什么是栈?

01.2 对于栈的操作

02栈的实际应用

02.1 逆波兰表示法

02.2 中缀表达法转后缀表达法

02.3 括号匹配

02.4 十进制转换为二进制

02.5 回文判定


前言

此学习笔记来源 嵌入式技术公开课 数据结构教程 

此学习笔记持续更新......欢迎交流。

00数据结构开篇

数据结构+算法=程序

算法:计算机处理问题的步骤

数据结构:作为处理对象的数据的摆列方式

数据才是程序的中心

数据结构就是组织数据最有效的摆列方式

高级程序员:数据结构+算法+数学思想+流程控制+逻辑思维

数据结构:

1,基础数据结构:栈,队列,树,链表

2,图

3,排序

4,查找/搜索

5,高级数据结构

算法:

贪心算法,分制发,动态规划,回朔法

01栈的实现原理

数组+循环 == 栈 队列

01.1 什么是栈

...... 类似于弹夹 ...进电梯  ...箱里的书
后入先出   先入后出

栈里的内容可以是任意数据类型数组存放的内容

01.2 对于栈的操作

入栈 出栈 判断栈是否为空

指针一直指向栈顶空白

代码实例

#include <stdio.h>

char stack[512];
int top = 0;

void push(char c);
char pop(void);
int is_empty(void);

int main(void)
{
	push('a');
	push('b');
	push('c');

	while(!is_empty())
	{
		putchar(pop());
	}
	printf("\n");

	return 0;
}

void push(char c)
{
	stack[top++] = c;
}

char pop(void)
{
	return stack[--top];
}

int is_empty(void)
{
/*
	if(top == 0)
		return 1;
	else
		return 0;
*/
	return top == 0;
}

02栈的实际应用

02.1 逆波兰表示法

想一想计算机实现下列运算?

5*(((8+9)*(4*6))+7)

计算的开始 有不确定性

那么如何才能把这种不确定性转化位决定性!

如果有(1+2)*(3-4)

逆波兰表示 12+34-*

从左到右 遇到数字入栈 遇到操作符 连续两次出栈并计算  结果入栈

最后得出什么? 没错就是遵守四则运算后的结果

在算算89+46**7+5*  看看结果是否跟你想的一样!

下面给出具体实现的代码

#include <stdio.h>
#include <string.h>

int stack[512];
int top = 0;

void push(int c);
int pop(void);
int is_empty(void);

int main(void)
{
	char a[100];
	int n;
	int i;
	int n1, n2;

	printf("Please enter a reverse polish expression:\n");
	gets(a);
	n = strlen(a);
	
	for(i = 0; i < n; i++)
	{
		if((a[i] >= '0') && (a[i] <= '9'))
			push(a[i] - '0');
		else
		{
			n2 = pop();
			n1 = pop();
			switch(a[i])
			{
				case '+':
					push(n1 + n2);
					break;
				case '-':
					push(n1 - n2);
					break;
				case '*':
					push(n1 * n2);
					break;
			}
		}
	}
	printf("result = %d\n", pop());

	return 0;
}

void push(int c)
{
	stack[top++] = c;
}

int pop(void)
{
	return stack[--top];
}

int is_empty(void)
{
/*
	if(top == 0)
		return 1;
	else
		return 0;
*/
	return top == 0;
}

02.2 中缀表达法转后缀表达法

在02.1中 我们说(1+2)*(3-4)这种常规的表示方法为中缀表达法 而加工后 12+34-* 这种为后缀表达法 那么如何实现 中缀表达法 转化为后缀表达法?

给出算法思想

((1+2)*(3-4))

  1. 从左至右来处理数据
  2. 当遇到左括号时,忽略它
  3. 当遇到数值时,直接输出
  4. 当遇到操作符时 将操作符入栈
  5. 当遇到右括号时,出栈栈顶的操作符

 代码具体实现

#include <stdio.h>
#include <string.h>

char stack[512];
int top = 0;

void push(char c);
char pop(void);
int is_empty(void);

int main(void)
{
	char str[100];
	int i, len;

	printf("Please enter a calcuate expression:");
	gets(str);
	
	len = strlen(str);

	for(i = 0; i < len; i++)
	{
		if(str[i] == '(')
			continue;
		else if((str[i] >= '0') && (str[i] <= '9'))
			printf("%c", str[i]);
		else if((str[i] == '+') || (str[i] == '-') || (str[i] == '*'))
			push(str[i]);
		else if(str[i] == ')')
			printf("%c", pop());
	}
	printf("\n");

	return 0;
}

void push(char c)
{
	stack[top++] = c;
}

char pop(void)
{
	return stack[--top];
}

int is_empty(void)
{
/*
	if(top == 0)
		return 1;
	else
		return 0;
*/
	return top == 0;
}

02.3 括号匹配

问题引入——你能在四则运算中准确地找到左括号对应的右括号吗!

示例: a[6]=(())()

1-2
0-3
4-5

算法思想:从左往右找 (遇到左括号先忽略) 遇到右括号开始找最近的未被匹配的左括号
        程序上就是:左括号入栈 遇到右括号出栈

如何把编号打进去?
        将编号代替左括号入栈

编程实现

#include <stdio.h>
#include <string.h>

int stack[512];
int top = 0;

void push(int c);
int pop(void);
int is_empty(void);

int main(void)
{
	char str[100];
	int i, len;

	printf("Please enter a calculate expression:");
	gets(str);
	len = strlen(str);

	for(i = 0; i < len; i++)
	{
		if(str[i] == '(')
			push(i);
		else if(str[i] == ')')
			printf("%d %d\n", pop(), i);
	}

	return 0;
}

void push(int c)
{
	stack[top++] = c;
}

int pop(void)
{
	return stack[--top];
}

int is_empty(void)
{
/*
	if(top == 0)
		return 1;
	else
		return 0;
*/
	return top == 0;
}

02.4 十进制转换为二进制

问题引入——如何将十进制13转换为二进制?

算法思想

1.判断n是不是为0 (n!=0),n%2 更新n的值(n=n/2)

2.重复第一步的操作,直到运行为n=0时为止

13

13%2 = 1    13/2 = 6

6%2 = 0     6/2 = 3

3%2=1      3/2=1

1%2 =1     1/2 = 0

3.只要栈不为空,就弹出栈顶内容,打印显示就是我们转换的结果

编程实现

#include <stdio.h>

int stack[512];
int top = 0;

void push(int c);
int pop(void);
int is_empty(void);

int main(void)
{
	int num;

	printf("Please enter an integer in decimal:");
	scanf("%d", &num);

	while(num)
	{
		push(num % 2);
		num /= 2;
	}

	while(!is_empty())
		printf("%d", pop());

	printf("\n");
	return 0;
}

void push(int c)
{
	stack[top++] = c;
}

int pop(void)
{
	return stack[--top];
}

int is_empty(void)
{
/*
	if(top == 0)
		return 1;
	else
		return 0;
*/
	return top == 0;
}

02.5 回文判定

什么是回文数?
      正着写 反着写 都一样的一行字符就是。比如 abccba  12344321
 

算法思想

1.求出字符串的长度,将前一半的字符依次入栈
2.如果栈不为空,出栈栈顶元素,将其与后半部分的字符串进行比较。如果字符串长度是奇数的话,要跳过中心点的元素,比较中心点后面的元素
3.如果比较的元素是相等的,一直比较 直到栈为空。这时返回是回文,如果比较不等,立刻停止比较,返回非回文。

编程实现

#include <stdio.h>
#include <string.h>

char stack[512];
int top = 0;

void push(char c);
char pop(void);
int is_empty(void);
int is_palindrom(char *pt);

int main(void)
{
	char str[100];

	printf("Please enter a string:");
	gets(str);

	if(is_palindrom(str))
		printf("str is a palindrom.\n");
	else
		printf("str is not a palindrom.\n");


	return 0;
}

void push(char c)
{
	stack[top++] = c;
}

char pop(void)
{
	return stack[--top];
}

int is_empty(void)
{
/*
	if(top == 0)
		return 1;
	else
		return 0;
*/
	return top == 0;
}

int is_palindrom(char *pt)
{
	int len, i;

	len = strlen(pt);

	for(i = 0; i < len/2; i++)
		push(pt[i]);

	if(len % 2 == 1)
		i++;

	while(!is_empty())
	{
		if(pop() == pt[i])
			i++;
		else
			return 0;
	}
	return 1;
}

猜你喜欢

转载自blog.csdn.net/shelter1234567/article/details/129394248