复习:数组、指针和数组指针的关系
数组是一串连续的存储空间,数组名对应的是存储空间的首地址,比较安全、
指针有多样性,不安全,但是灵活,容易出现野指针
数组指针的本质是数组,数组里的元素是指针
---------------------------------------------------------------------------------------------------------------------------------
链式物理结构的动态分配内存、释放
链式物理结构中每个有效结点都应该是动态分配的
链式物理结构中能容纳的数字数量可以灵活变化
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int num;
struct node *p_next;
} node;
int main()
{
int num = 0;
node head = {0},tail = {0},*p_tmp = NULL,*p_node = NULL;
head.p_next = &tail;
while (1)
{
printf("请输入一个数字:");
scanf("%d",&num);
if (num < 0)
{
break;
}
p_tmp = malloc(sizeof(node));
if (!p_tmp)
{
continue;
}
p_tmp->num = num;
p_tmp->p_next = NULL;
for (p_node = &head;p_node != &tail;p_node = p_node->p_next)
{
node *p_first = p_node;
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
if (p_mid == &tail) //插在最后的位置
{
p_first->p_next = p_tmp;
p_tmp->p_next = p_mid;
break;
}
}
}
for (p_node = &head;p_node != &tail;p_node = p_node->p_next)
{
node *p_first = p_node;
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
if (p_mid != &tail)
{
printf("%d",p_mid->num);
}
}
printf("\n");
释放内存 while (head.p_next != &tail) // 只要存在有效节点,循环就继续
{
node *p_first = &head;
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
p_first->p_next = p_last; // 先摘出来再释放
free(p_mid);
p_mid = NULL;
}
return 0;
删除一个点时要释放内存:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int num;
struct node *p_next;
} node;
int main()
{
int num = 0;
node head = {0},tail = {0},*p_tmp = NULL,*p_node = NULL;
head.p_next = &tail;
while (1)
{
printf("请输入一个数字:");
scanf("%d",&num);
if (num < 0)
{
break;
}
p_tmp=(node *)malloc(sizeof(node));
if (!p_tmp)
{
continue;
}
p_tmp->num = num;
p_tmp->p_next = NULL;
for (p_node = &head;p_node != &tail;p_node = p_node->p_next)
{
node *p_first = p_node;
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
if (p_mid == &tail)
{
p_first->p_next = p_tmp;
p_tmp->p_next = p_mid;
break;
}
}
}
printf("请输入删除数字:");
scanf("%d",&num);
for (p_node = &head;p_node != &tail;p_node = p_node->p_next)
{
node *p_first = p_node;
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
if (p_mid != &tail && p_mid->num == num)
{
p_first->p_next = p_last; //先摘了,再释放
free(p_mid);
p_mid = NULL;
break;
}
}
for (p_node = &head;p_node != &tail;p_node = p_node->p_next)
{
node *p_first = p_node;
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
if (p_mid != &tail)
{
printf("%d",p_mid->num);
}
}
printf("\n");
while (head.p_next != &tail)
{
node *p_first = &head;
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
p_first->p_next = p_last;
free(p_mid);
p_mid = NULL;
}
return 0;
栈
栈是一种数据结构,栈里可以存放数字,数字有前后顺序,先放到栈里的数字在前面,后放到栈里的数字在后面
从栈里获得的数字一定是最后一个放进去的数字
这种使用数字的方法叫做后进先出
在实现入栈的时候需要提供一个push函数,它负责向栈里放一个数字
在实现出栈的时候需要提供一个pop函数,它负责从栈里获得一个数字
栈的顺序存储结构:
准备工作:
1#include<stdio.h>
2typedef struct{
3 int buf[size];
4 int qty; //已经往数组(栈)里放了几个数
5}stack;
6//初始化函数
7void stack_init(stack *p_stack){ //定义一个stack结构体类型的指针
8 p_stack->qty=0; //让栈里的数据为0
9 }
10//清理函数
11void stack_deinit(stack *p_stack){//定义一个stack结构体类型的指针
12 p_stack->qty=0;
13 }
14//判断栈是不是空函数
15int stack_empty(const stack *p_stack){//加const关键字,不能改变指针所指向地址的内容,但可以改变地址的指向
16 return !(p_stack->qty);
17 }
18//判断栈是不是满的
19int stack_full(const stack *p_stack){
20 return p_stack->qty==SIZE;
21 }
22//需要获得栈里的数字个数
23 int stack_size(const stack *p_stack){
24 return p_stack->qty
25 }
26//向栈里放数字的函数
27void stack_push(stack *p_stack,int num){
28 p_stack->buf[p_stack->qty]=num;
29 p_stack->qty++;
30 }
31//从栈里拿走最后一个数字
32int stack_pop(stack *p_stack){
33 p_stack->qty--;
34 return p_stack->buf[p_stack->qty];
35 }
36//获得栈里最后一个数字
37int stack_top(const stack *p_stack){
38 return p_stack->buf[p_stack->qty-1];
39 }
编写源函数:
#include "02stack.h"
//初始化函数
void stack_init(stack *p_stack) {
p_stack->qty = 0;
}
//清理函数
void stack_deinit(stack *p_stack) {
p_stack->qty = 0;
}
//判断栈是不是空的函数
int stack_empty(const stack *p_stack) {
return !(p_stack->qty);
}
//判断栈是不是满的函数
int stack_full(const stack *p_stack) {
return p_stack->qty == SIZE;
}
//获得栈里的数字个数
int stack_size(const stack *p_stack) {
return p_stack->qty;
}
//向栈里放数字的函数
void stack_push(stack *p_stack, int num) {
p_stack->buf[p_stack->qty] = num;
p_stack->qty++;
}
//从栈里拿走最后一个数字
int stack_pop(stack *p_stack) {
p_stack->qty--;
return p_stack->buf[p_stack->qty];
}
//获得栈里最后一个数字
int stack_top(const stack *p_stack) {
return p_stack->buf[p_stack->qty - 1];
}
编写头文件:02stack.h
#ifndef __02STACK_H__
#define __02STACK_H__
typedef struct {
int buf[SIZE];
int qty;
} stack;
//初始化函数
void stack_init(stack *);
//清理函数
void stack_deinit(stack *);
//判断栈是不是空的函数
int stack_empty(const stack *);
//判断栈是不是满的函数
int stack_full(const stack *);
//获得栈里的数字个数
int stack_size(const stack *);
//向栈里放数字的函数
void stack_push(stack *, int );
//从栈里拿走最后一个数字
int stack_pop(stack *);
//获得栈里最后一个数字
int stack_top(const stack *);
#endif //__02STACK_H__
编写主函数(测试用):
/*
栈测试
*/
#include <stdio.h>
#include "02stack.h"
int main() {
stack stk = {0};
stack_init(&stk);
stack_push(&stk, 10);
stack_push(&stk, 20);
stack_push(&stk, 30);
stack_push(&stk, 40);
stack_push(&stk, 50);
stack_push(&stk, 60);
printf("数字个数是%d\n", stack_size(&stk));
printf("判断满的结果是%d\n", stack_full(&stk));
printf("%d ", stack_pop(&stk));
printf("%d ", stack_pop(&stk));
printf("%d ", stack_pop(&stk));
printf("%d ", stack_pop(&stk));
printf("%d ", stack_pop(&stk));
printf("%d\n", stack_pop(&stk));
stack_deinit(&stk);
return 0;
}
输入指令 gcc –DSIZE=602main.c 02stack.c
栈的链式存储结构:
编写源函数:03stack.c
#include<stdlib.h>
#include"03stack.h"
//初始化函数
void stack_init(stack*p_stack) { //定义一个stack结构体类型的指针
//头结点和尾结点连起来 就什么数据内容都没有
p_stack->head.p_next =&(p_stack->tail);
p_stack->tail.p_next = NULL;
}
//清理函数
void stack_deinit(stack*p_stack) { //定义一个stack结构体类型的指针
//把所有有效结点删除
while (p_stack->head.p_next !=&(p_stack->tail)) {
node *p_first =&(p_stack->head);
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
p_first->p_next = p_last;
free(p_mid);
p_mid = NULL;
}
}
//判断栈是不是空的函数
int stack_empty(conststack *p_stack) {
//如果头结点指针是尾结点地址就是空的
return p_stack->head.p_next = =&(p_stack->tail);
}
//判断栈是不是满的函数
int stack_full(conststack *p_stack) {
return 0;
}
//获得栈里的数字个数
int stack_size(conststack *p_stack) {
//进栈个数编号加一就是个数
int cnt = 0;
const node *p_node = NULL;
for (p_node =&(p_stack->head);p_node != &(p_stack->tail);p_node =p_node->p_next) {
const node *p_first = p_node;
const node *p_mid = p_first->p_next;
const node *p_last = p_mid->p_next;
if (p_mid != &(p_stack->tail)) {
cnt++;
}
}
return cnt;
}
//向栈里放数字的函数
void stack_push(stack*p_stack, int num) {
node *p_first = NULL, *p_mid = NULL, *p_last= NULL;
node *p_tmp = (node *)malloc(sizeof(node));
if (!p_tmp) {
return ;
}
p_tmp->num = num;
p_tmp->p_next = NULL;
p_first = &(p_stack->head);
p_mid = p_first->p_next;
p_last = p_mid->p_next;
p_first->p_next = p_tmp; //把数放在first和mid之间
p_tmp->p_next = p_mid;
}
//从栈里拿走最后一个数字
int stack_pop(stack*p_stack) {
int ret = 0;
node *p_first = &(p_stack->head);
node *p_mid = p_first->p_next;
node *p_last = p_mid->p_next;
p_first->p_next = p_last;
ret = p_mid->num;
free(p_mid);
p_mid = NULL;
return ret;
}
//获得栈里最后一个数字
int stack_top(conststack *p_stack) {
return p_stack->head.p_next->num;
}
改写成头文件:03stack.h
#ifndef __03STACK_H__
#define __03STACK_H__
typedef struct node {
int num;
struct node *p_next;
} node;
typedef struct {
node head, tail;
} stack;
//初始化函数
void stack_init(stack*);
//清理函数
void stack_deinit(stack*);
//判断栈是不是空的函数
int stack_empty(conststack *);
//判断栈是不是满的函数
int stack_full(conststack *);
//获得栈里的数字个数
int stack_size(conststack *);
//向栈里放数字的函数
void stack_push(stack*, int );
//从栈里拿走最后一个数字
int stack_pop(stack *);
//获得栈里最后一个数字
int stack_top(conststack *);
#endif //__03STACK_H__
编写主函数:03main.c
/*
栈测试
*/
#include<stdio.h>
#include "03stack.h"
int main() {
stack stk = {0};
stack_init(&stk);
stack_push(&stk, 10);
stack_push(&stk, 20);
stack_push(&stk, 30);
stack_push(&stk, 40);
stack_push(&stk, 50);
stack_push(&stk, 60);
printf("数字个数是%d\n",stack_size(&stk));
printf("判断满的结果是%d\n",stack_full(&stk));
printf("%d ",stack_pop(&stk));
printf("%d ",stack_pop(&stk));
printf("%d ",stack_pop(&stk));
printf("%d ",stack_pop(&stk));
printf("%d ",stack_pop(&stk));
printf("%d\n", stack_pop(&stk));
stack_deinit(&stk);
return 0;
}
输入指令: gcc –DSIZE=6 03main.c 03stack.c
栈练习:
3*4+2-6/3:
#include <stdio.h>
#include "02stack.h"
int main() {
int num = 0, num1 = 0, opr = 0;
stack stk = {0};
char buf[50] = {0}, *p_ch = buf;
printf("请输入一个公式:");
fgets(buf, 50, stdin);
stack_init(&stk);
while (1) {
if (*p_ch >= '0' && *p_ch <= '9') {
stack_push(&stk, *p_ch - '0');
}
else if (*p_ch == '*' || *p_ch == '/') {
num = stack_pop(&stk);
num1 = *(p_ch + 1) - '0';
if (*p_ch == '*') {
stack_push(&stk, num *num1);
}
else {
stack_push(&stk, num /num1);
}
p_ch++;
}
else if (*p_ch == '+' || *p_ch== '-') {
if (stack_size(&stk) == 3) {
num1 = stack_pop(&stk);
opr = stack_pop(&stk);
num = stack_pop(&stk);
if (opr == '+') {
stack_push(&stk, num +num1);
}
else {
stack_push(&stk, num -num1);
}
}
stack_push(&stk, *p_ch);
}
else {
if (stack_size(&stk) == 3) {
num1 = stack_pop(&stk);
opr = stack_pop(&stk);
num = stack_pop(&stk);
if (opr == '+') {
printf("计算结果是%d\n", num + num1);
}
else {
printf("计算结果是%d\n", num - num1);
}
}
else {
printf("计算结果是%d\n",stack_pop(&stk));
}
break;
}
p_ch++;
}
stack_deinit(&stk);
return 0;
}
输入指令:gcc-DSIZE=10 04operand.c 02stack.c