队列:
定义:队列是一种数据结构,可以用来存储数字,在队列里是有顺序的
获得的数字是最先放进去的数字,先进先出
实现队列的用法需要提供一个函数用来向队列里放数字(PUSH),也需要一个函数从队列里获得数字(POP)
队列的顺序存储结构:
编写函数模板:
1 typedef struct{
2 int buf[SIZE];
3 int head;//第一个数字所在存储区的下标
4 int tail;//第一个空位置所在的下标(最后一个数字的下一个下标 tail=size)
5}queue;
6//初始化函数
7void queue_init(queue *p_queue){
8 p_queue->head=0;
9 p_queue->tail=0;
10 }
11//清理函数
12void queue_deinit(queue *p_queue){
13 p_queue->head=0;
14 p_queue->head=0;
15 }
16//判断队列是否空的函数
17int queue_empty(const queue *p_queue){
18 return p_queue->head==p_queue->tail;
19 }
20//判断队列是否满的函数
21int queue_full(const queue *p_queue){
22 return p_queue->tail==SIZE;
23 }
24 //获得数字个数的函数
25int queue_size(const queue *p_queue){
26 //每多一个数tail+1,每少一个数head加一
27 return p_queue->tail-p_queue->head;
28 }
29//向队列里添加数字的函数
30void queue_push(queue *p_queue,int num){//要修改队列,不能加const
31 p_queue->buf[p_queue->tail]=num;
32 p_queue->tail++;
33 }
34//从队列里拿走数字的函数
35int queue_pop(queue *p_queue){
36 int ret=p_queue->buf[p_queue->head];//队列是拿走先进来的数组
37 p_queue->head++;
38 }
39//从队列里获得数字的函数
40int queue_front(const queue *p_queue){
41 return p_queue->buf[p_queue->head];//获得队列的头部
42 }
编写源文件:01queue.c
#include "01queue.h"
//初始化函数
void queue_init(queue *p_queue) {
p_queue->head = 0;
p_queue->tail = 0;
}
//清理函数
void queue_deinit(queue *p_queue) {
p_queue->head = 0;
p_queue->tail = 0;
}
//判断队列是否空的函数
int queue_empty(const queue *p_queue) {
return p_queue->head == p_queue->tail;
}
//判断队列是否满的函数
int queue_full(const queue *p_queue) {
return p_queue->tail == SIZE;
}
//获得数字个数的函数
int queue_size(const queue *p_queue) {
return p_queue->tail - p_queue->head;
}
//向队列里添加数字的函数
void queue_push(queue *p_queue, int num) {
p_queue->buf[p_queue->tail] = num;
p_queue->tail++;
}
//从队列里拿走数字的函数
int queue_pop(queue *p_queue) {
int ret = p_queue->buf[p_queue->head];
p_queue->head++;
return ret;
}
//从队列里获得数字的函数
int queue_front(const queue *p_queue) {
return p_queue->buf[p_queue->head];
}
改写成头文件:01queue.h
typedef struct {
int buf[SIZE];
int head/*第一个数字所在存储区的下标*/,tail/*第一个空位置所在的下标*/;
} queue;
//初始化函数
void queue_init(queue *);
//清理函数
void queue_deinit(queue *);
//判断队列是否空的函数
int queue_empty(const queue *);
//判断队列是否满的函数
int queue_full(const queue *);
//获得数字个数的函数
int queue_size(const queue *);
//向队列里添加数字的函数
void queue_push(queue *, int );
//从队列里拿走数字的函数
int queue_pop(queue *);
//从队列里获得数字的函数
int queue_front(const queue *);
#endif //__01QUEUE_H__
编写主函数:
#include <stdio.h>
#include "01queue.h"
int main() {
queue que = {0};
queue_init(&que);
queue_push(&que, 10);
queue_push(&que, 20);
queue_push(&que, 30);
queue_push(&que, 40);
queue_push(&que, 50);
queue_push(&que, 60);
printf("数字个数是%d\n", queue_size(&que)); //计算一共放了几个
printf("%d\n", queue_pop(&que)); //拿数
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("判断满的结果是%d\n", queue_full(&que));
if (!queue_full(&que)) {
queue_push(&que, 70);
queue_push(&que, 80);
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
}
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("判断空的结果是%d\n", queue_empty(&que));
queue_deinit(&que);
return 0;
}
输入指令 gcc-DSIZE=6 1.c 01.c
gcc -DSIZE=10 1.c 01.c
循环队列:编写队列,如果拿走头部的数,头部就空了,继续往队列放数,当放满了之后开始往头部放
编写源文件:02queue.c
#include "02queue.h"
//初始化函数
void queue_init(queue *p_queue) {
p_queue->head = 0;
p_queue->tail = 0;
p_queue->num = 0;
}
//清理函数
void queue_deinit(queue *p_queue) {
p_queue->head = 0;
p_queue->tail = 0;
p_queue->num = 0;
}
//判断队列是否空的函数
int queue_empty(const queue *p_queue) { //不会做改变,加个const
return !(p_queue->num);
}
//判断队列是否满的函数
int queue_full(const queue *p_queue) {
return p_queue->num == SIZE;
}
//获得数字个数的函数
int queue_size(const queue *p_queue) {
return p_queue->num;
}
//向队列里添加数字的函数
void queue_push(queue *p_queue, int num) {
p_queue->buf[p_queue->tail] = num; //用tail做下标找到这个数
p_queue->num++;
p_queue->tail = (p_queue->tail + 1) %SIZE; //若尾部满了则绕回头部放数
}
//从队列里拿走数字的函数
int queue_pop(queue *p_queue) {
int ret = p_queue->buf[p_queue->head];
p_queue->num--;
p_queue->head = (p_queue->head + 1) % SIZE;
return ret;
}
//从队列里获得数字的函数
int queue_front(const queue *p_queue) {
return p_queue->buf[p_queue->head];
}
编写头文件:
#ifndef __02QUEUE_H__
#define __02QUEUE_H__
typedef struct {
int buf[SIZE];
int head/*第一个数字所在存储区的下标*/,tail/*第一个空位置所在的下标*/;
int num;
} queue;
//初始化函数
void queue_init(queue *);
//清理函数
void queue_deinit(queue *);
//判断队列是否空的函数
int queue_empty(const queue *);
//判断队列是否满的函数
int queue_full(const queue *);
//获得数字个数的函数
int queue_size(const queue *);
//向队列里添加数字的函数
void queue_push(queue *, int );
//从队列里拿走数字的函数
int queue_pop(queue *);
//从队列里获得数字的函数
int queue_front(const queue *);
#endif //__02QUEUE_H__
编写主函数: 02main.c
#include <stdio.h>
#include "02queue.h"
int main() {
queue que = {0};
queue_init(&que); //初始化
queue_push(&que, 10); //放数
queue_push(&que, 20);
queue_push(&que, 30);
queue_push(&que, 40);
queue_push(&que, 50);
queue_push(&que, 60);
printf("数字个数是%d\n", queue_size(&que)); //计算一共放了几个
printf("%d\n", queue_pop(&que)); //拿数
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("判断满的结果是%d\n", queue_full(&que));
if (!queue_full(&que)) {
queue_push(&que, 70);
queue_push(&que, 80);
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
}
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("判断空的结果是%d\n", queue_empty(&que));
queue_deinit(&que); //清空
return 0;
}
输入指令: gcc -DSIZE=6 02.c main2.c
执行结果:
数字个数是:6
10
20
30
判断满的结果是; 0
40
50
60
70
80
判断空的结果是:1 (1为真)
队列的链式存储结构:
编写源文件:03queue.c
#include <stdlib.h>
#include "03queue.h"
//初始化函数
void queue_init(queue *p_queue) {
p_queue->head.p_next = &(p_queue->tail);
p_queue->tail.p_next = NULL;
}
//清理函数
void queue_deinit(queue *p_queue) {
while (p_queue->head.p_next != &(p_queue->tail)) {
node *p_first = &(p_queue->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 queue_empty(const queue *p_queue) {
return p_queue->head.p_next == &(p_queue->tail);
}
//判断队列是否满的函数
int queue_full(const queue *p_queue) {
return 0;
}
//获得数字个数的函数
int queue_size(const queue *p_queue) {
int cnt = 0;
const node *p_node = NULL;
for (p_node = &(p_queue->head);p_node !=&(p_queue->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_queue->tail)) {
cnt++;
}
}
return cnt;
}
//向队列里添加数字的函数
void queue_push(queue *p_queue, int num) {
node *p_node = NULL;
node *p_tmp = (node *)malloc(sizeof(node));
if (!p_tmp) { //如果分配失败,则返回
return ;
}
p_tmp->num = num; //如果分配成功
p_tmp->p_next = NULL;
for (p_node = &(p_queue->head);p_node !=&(p_queue->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 == &(p_queue->tail)) {
p_first->p_next = p_tmp;
p_tmp->p_next = p_mid;
break;
}
}
}
//从队列里拿走数字的函数
int queue_pop(queue *p_queue) {
node *p_first = NULL, *p_mid = NULL, *p_last = NULL;
int ret = p_queue->head.p_next->num;
p_first = &(p_queue->head);
p_mid = p_first->p_next;
p_last = p_mid->p_next;
p_first->p_next = p_last;
free(p_mid);
p_mid = NULL;
return ret;
}
//从队列里获得数字的函数
int queue_front(const queue *p_queue) {
return p_queue->head.p_next->num;
}
编写头文件:03queue.h
#ifndef __03QUEUE_H__
#define __03QUEUE_H__
typedef struct node {
int num;
struct node *p_next;
} node;
typedef struct {
node head, tail;
} queue;
//初始化函数
void queue_init(queue *);
//清理函数
void queue_deinit(queue *);
//判断队列是否空的函数
int queue_empty(const queue *);
//判断队列是否满的函数
int queue_full(const queue *);
//获得数字个数的函数
int queue_size(const queue *);
//向队列里添加数字的函数
void queue_push(queue *, int );
//从队列里拿走数字的函数
int queue_pop(queue *);
//从队列里获得数字的函数
int queue_front(const queue *);
#endif //__03QUEUE_H__
编写主函数:03main.c
#include <stdio.h>
#include "03queue.h"
int main() {
queueque = {0};
queue_init(&que);
queue_push(&que, 10);
queue_push(&que, 20);
queue_push(&que, 30);
queue_push(&que, 40);
queue_push(&que, 50);
queue_push(&que, 60);
printf("数字个数是%d\n", queue_size(&que));
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("判断满的结果是%d\n", queue_full(&que));
if (!queue_full(&que)) {
queue_push(&que, 70);
queue_push(&que, 80);
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
}
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("%d\n", queue_pop(&que));
printf("判断空的结果是%d\n", queue_empty(&que));
queue_deinit(&que);
return 0;
}
链表
链表也是一种数据结构,它用来对链式物理结构进行管理
链表用来把链式物理结构的管理代码和其它代码分隔开
链表的功能主要包含插入、删除、查找和遍历
单向链表:
链表一般用链式物理结构
编写源文件:04link.c
#include<stdlib.h>
#include"04link.h"
//初始化函数
void link_init(link*p_link) {
p_link->head.p_next =&(p_link->tail);
p_link->tail.p_next = NULL;
}
//清理函数
void link_deinit(link*p_link) {
while (p_link->head.p_next !=&(p_link->tail)) {
node *p_first = &(p_link->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 link_size(constlink *p_link) {
int cnt = 0;
const node *p_node = NULL;
for (p_node = &(p_link->head);p_node!= &(p_link->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_link->tail)) {
cnt++;
}
}
return cnt;
}
//在链表头加入数字
void link_add_head(link*p_link, 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_link->head);
p_mid = p_first->p_next;
p_last = p_mid->p_next;
p_first->p_next = p_tmp;
p_tmp->p_next = p_mid;
}
//在链表末尾追加数字
void link_append(link*p_link, int num) {
node *p_tmp = (node *)malloc(sizeof(node));
node *p_node = NULL;
if (!p_tmp) {
return ;
}
p_tmp->num = num;
p_tmp->p_next = NULL;
for (p_node = &(p_link->head);p_node!= &(p_link->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 == &(p_link->tail)) {
p_first->p_next = p_tmp;
p_tmp->p_next = p_mid;
break;
}
}
}
//按顺序加入数字的函数
voidlink_insert_in_order(link *p_link, int num) {
node *p_node = NULL;
node *p_tmp = (node *)malloc(sizeof(node));
if (!p_tmp) {
return ;
}
p_tmp->num = num;
p_tmp->p_next = NULL;
for (p_node = &(p_link->head);p_node!= &(p_link->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 == &(p_link->tail) ||p_mid->num > num) {
p_first->p_next = p_tmp;
p_tmp->p_next = p_mid;
break;
}
}
}
//删除最前边数字的函数
voidlink_remove_head(link *p_link) {
node *p_first = NULL, *p_mid = NULL,*p_last = NULL;
p_first = &(p_link->head);
p_mid = p_first->p_next;
p_last = p_mid->p_next;
p_first->p_next = p_last;
free(p_mid);
p_mid = NULL;
}
//删除最后一个结点的函数
voidlink_remove_tail(link *p_link) {
node *p_node = NULL;
for (p_node = &(p_link->head);p_node!= &(p_link->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_last == &(p_link->tail)) {
p_first->p_next = p_last;
free(p_mid);
p_mid = NULL;
break;
}
}
}
//获得最前面数字的函数
int link_get_head(constlink *p_link, int *p_num) {
if (p_link->head.p_next ==&(p_link->tail)) {
return 0;
}
else {
*p_num =p_link->head.p_next->num;
return 1;
}
}
//获得最后一个数字的函数
int link_get_tail(link*p_link, int *p_num) {
node *p_node = NULL;
for (p_node = &(p_link->head);p_node!= &(p_link->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_last == &(p_link->tail)) {
*p_num = p_mid->num;
return 1;
}
}
return 0;
}
改写头文件:04link.h
#ifndef __04LINK_H__
#define __04LINK_H__
typedef struct node {
int num;
struct node *p_next;
} node;
typedef struct {
node head, tail;
} link;
//初始化函数
void link_init(link *);
//清理函数
void link_deinit(link *);
//获得有效数字个数的函数
int link_size(const link *);
//在链表头加入数字
void link_add_head(link *, int );
//在链表末尾追加数字
void link_append(link *, int );
//按顺序加入数字的函数
void link_insert_in_order(link *, int );
//删除最前边数字的函数
void link_remove_head(link *);
//删除最后一个结点的函数
void link_remove_tail(link *);
//获得最前面数字的函数
int link_get_head(const link *, int *);
//获得最后一个数字的函数
int link_get_tail(link *, int *);
#endif //__04LINK_H__
编写主函数:04main.c
#include <stdio.h>
#include "04link.h"
int main() {
int num = 0;
node *p_node = NULL;
link lnk = {0};
link_init(&lnk);
link_add_head(&lnk, 10);
link_append(&lnk, 100);
link_insert_in_order(&lnk, 70);
link_insert_in_order(&lnk, 20);
link_insert_in_order(&lnk, 40);
link_insert_in_order(&lnk, 30);
link_insert_in_order(&lnk, 50);
printf("数字个数是%d\n", link_size(&lnk));
for (p_node = &(lnk.head);p_node != &(lnk.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 != &(lnk.tail)) {
printf("%d ", p_mid->num);
}
}
printf("\n");
link_remove_head(&lnk);
link_remove_tail(&lnk);
link_get_head(&lnk, &num);
printf("最前边的数字是%d\n", num);
link_get_tail(&lnk, &num);
printf("最后边的数字是%d\n", num);
printf("数字个数是%d\n", link_size(&lnk));
for (p_node = &(lnk.head);p_node != &(lnk.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 != &(lnk.tail)) {
printf("%d ", p_mid->num);
}
}
printf("\n");
link_deinit(&lnk);
return 0;
}
目前还不完整,(遍历打印不能写在主函数里),明天继续改造