<2014 05 16> 线性表、栈与队列——一个环形队列的C语言实现
栈与队列都是具有特殊存取方式的线性表,栈属于先进后出(FILO),而队列则是先进先出(FIFO)。栈能够将递归问题转化为非递归问题,这是它的一个重要特性。除了FILO、FIFO这样的最普遍存取方式外,还有一些扩展的数据结构,如双端队列、双栈、超队列、超栈等,它们是一种扩展与变异结构。
线性表有顺序存储和链接存储两类,这是针对计算机的线性存储空间作出的分类。前者可以是数组,后者可以是链表。字符串是线性表最常见的应用。
这里我用C语言实现了一个基于数组环形队列,它具有固定的队列空间。相比于链表实现,它非常小巧和高效,特别是在负载可预计的情况下。
//fifo.h
#ifndef __FIFO_H__
#define __FIFO_H__ #define FIFO_LENGTH 20
#define EMPTY 0x00
#define FULL 0x01
#define NORMAL 0x02 typedef struct require_fifo{
int item[FIFO_LENGTH];
int read_ptr;
int write_ptr;
int flag;
}fifo; extern fifo* fifo_create(void);
extern void fifo_destroy(fifo* fifo_ptr);
extern void fifo_in(fifo* fifo_ptr, int data);
extern int fifo_out(fifo* fifo_ptr); #endif
//fifo.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <memory.h>
#include "fifo.h" fifo* fifo_create(void);
void fifo_destroy(fifo* fifo_ptr);
void fifo_in(fifo* fifo_ptr, int data);
int fifo_out(fifo* fifo_ptr); fifo* fifo_create(void){
fifo *fifo_ptr = malloc(sizeof(fifo));
memset(fifo_ptr, , sizeof(fifo));
fifo_ptr->write_ptr = ;
fifo_ptr->read_ptr = ;
fifo_ptr->flag = EMPTY;
return fifo_ptr;
} void fifo_destroy(fifo* fifo_ptr){
free(fifo_ptr);
printf("destroy fifo \n");
} void fifo_in(fifo* fifo_ptr, int data){
if(fifo_ptr->flag != FULL ){
fifo_ptr->item[fifo_ptr->write_ptr] = data;
fifo_ptr->write_ptr ++;
fifo_ptr->write_ptr %= FIFO_LENGTH;
if((fifo_ptr->write_ptr - fifo_ptr->read_ptr) == -){
fifo_ptr->flag = FULL;
}else{
fifo_ptr->flag = NORMAL;
}
//printf("write_ptr = %d \n", fifo_ptr->write_ptr);
}else{
printf("fifo is full, write invalide\n");
}
} int fifo_out(fifo* fifo_ptr){
int data = ; if(fifo_ptr->flag != EMPTY){
data = fifo_ptr->item[fifo_ptr->read_ptr];
fifo_ptr->read_ptr ++;
fifo_ptr->read_ptr %= FIFO_LENGTH;
if((fifo_ptr->write_ptr - fifo_ptr->read_ptr) == ){
fifo_ptr->flag = EMPTY;
}
//printf("read_ptr = %d \n", fifo_ptr->read_ptr);
return data;
}else{
printf("fifo is empty, read invalide\n");
return -;
} return -;
}
我们可以写一个测试代码来测试它的性能:
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include "../fifo.h" pthread_mutex_t lock_fifo;
fifo* myfifo; void * producer_thread1(void *pin){
pin = NULL;
while(){
pthread_mutex_lock(&lock_fifo);
fifo_in(myfifo, );
pthread_mutex_unlock(&lock_fifo);
printf("producer1 put 1 into myfifo\n");
usleep();
}
return((void*));
} void * producer_thread2(void *pin){
pin = NULL;
while(){
pthread_mutex_lock(&lock_fifo);
fifo_in(myfifo, );
pthread_mutex_unlock(&lock_fifo);
printf("producer2 put 2 into myfifo\n");
usleep();
}
return((void*));
} void * consumer_thread1(void *pin){
int require = ;
pin = NULL; while(){
pthread_mutex_lock(&lock_fifo);
require = fifo_out(myfifo);
pthread_mutex_unlock(&lock_fifo);
printf(" consumer1 get %d form myfifo\n", require);
usleep();
}
return((void*));
} void * consumer_thread2(void *pin){
int require = ;
pin = NULL; while(){
pthread_mutex_lock(&lock_fifo);
require = fifo_out(myfifo);
pthread_mutex_unlock(&lock_fifo);
printf(" consumer2 get %d form myfifo\n", require);
usleep();
}
return((void*));
} void keyboard_exit(int signo){
printf("exit by keyboard \n");
fifo_destroy(myfifo);
_exit();
} int main(){
pthread_t th_producer1, th_producer2, th_consumer1, th_consumer2;
void * ret; pthread_mutex_init(&lock_fifo, NULL);
myfifo = fifo_create();
signal(SIGINT, keyboard_exit);
pthread_create(&th_producer1, NULL, producer_thread1, );
pthread_create(&th_producer2, NULL, producer_thread2, );
pthread_create(&th_consumer1, NULL, consumer_thread1, );
pthread_create(&th_consumer2, NULL, consumer_thread2, ); pthread_join(th_producer1, &ret);
pthread_join(th_producer2, &ret);
pthread_join(th_consumer1, &ret);
pthread_join(th_consumer2, &ret); while(){
printf("thread error\n");
}
return ;
}
写一个gcc的Makefile文件来编译链接:
CC = gcc
CFLAGS := -g -Wall
LIB := -lpthread
OBJ = ../fifo.o ./test.o
all: demo demo:test fifo
$(CC) $(CFLAGS) -o ./demo $(OBJ) $(LIB) test:
$(CC) $(CFLAGS) -o ./test.o -c ./test.c
fifo:
$(CC) $(CFLAGS) -o ../fifo.o -c ../fifo.c clean:
rm ./test.o ./demo ../fifo.o .PHONY: $(PHONY) clean
在test目录下运行./demo。
输出结果:
write_ptr =
producer1 put into myfifo
write_ptr =
producer2 put into myfifo
read_ptr =
consumer1 get form myfifo
read_ptr =
consumer2 get form myfifo
fifo is empty, read invalide
consumer1 get - form myfifo
fifo is empty, read invalide
consumer2 get - form myfifo
write_ptr =
producer2 put into myfifo
write_ptr =
producer1 put into myfifo
read_ptr =
consumer1 get form myfifo
read_ptr =
consumer2 get form myfifo
write_ptr =
producer2 put into myfifo
read_ptr =
。。。。
。。。。
^Cexit by keyboard
destroy fifo
<2014 05 16> 线性表、栈与队列——一个环形队列的C语言实现的更多相关文章
- [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)
循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...
- k:特殊的线性表—栈
栈(Stack): 栈是一种特殊的线性表,栈中的数据元素以及数据元素之间的逻辑关系和线性表相同,两者之间的差别在于:线性表的插入和删除操作可以在表的任意位置进行,而栈的插入和删除操作只允许在表的尾端 ...
- 数据结构-线性表的链式存储相关算法(C语言实现)
链表的简单介绍 为什么需要线性链表 当然是为了克服顺序表的缺点,在顺序表中,做插入和删除操作时,需要大量的移动元素,导致效率下降. 线性链表的分类 按照链接方式: 按照实现角度: 线性链表的创建和简单 ...
- 队列(Queue)--环形队列、优先队列和双向队列
1. 队列概述 队列和堆栈都是有序列表,属于抽象型数据类型(ADT),所有加入和删除的动作都发生在不同的两端,并符合First In, First Out(先进先出)的特性. 特性: ·FIFO ·拥 ...
- Java 单向队列及环形队列
队列的特点 1.可以使用数组和链表两种方式来实现. 2.遵循先入先出(FIFO)的规则,即先进入的数据先出. 3.属于有序列表. 图解实现过程: 1.定义一个固定长度的数组,长度为maxSize. ...
- c# 写着玩的,两个Task并发,一个写队列一个读队列的异常情况
class Program { class TestEnqueue { static Queue<string> str = new Queue<string>(); publ ...
- Java数据结构之线性表(2)
从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...
- java线性表学习笔记(一)
线性表是一种按顺序储存数据是的常用结构,大多数的线性表都支持以下的典型操作: 从线性表提取插入删除一个数据: 找出线性表中的某一个元素: 找出线性表中的元素: 确定线性表中是否包含某一个元素,确定线性 ...
- 线性表结构的Java实现
一.线性表的抽象数据类型表述 线性表的结构简单,长度允许动态增长或搜索:可以对线性表中的任何数据元素进行访问和查找:允许进行数据的插入和删除操作:求线性表中的指定数据的前驱和后继:合并线性表以及拆分线 ...
随机推荐
- 数据库出错提示Duplicate entry * for key *的解决方法
错误编号:1062 错误提示: 查询语句错误] ERR: Duplicate entry ' for key 'PRIMARY' SQL: ' PHP: misc.php: ; IP 问题分析: 向唯 ...
- Spring Boot(七):spring boot测试介绍
首先maven要引入spring-boot-starter-test这个包. 先看一段代码 @RunWith(SpringRunner.class) @SpringBootTest(webEnviro ...
- CentOS6X安装PHP5.5
CentOS6.x默认的php版本是php5.3,已经过时喽,现在最新的稳定版是5.5.38. 安装方法: 1.先下载2个源 rpm -Uvh https://dl.fedoraproject.org ...
- 浅谈iOS 5的StoryBoard
转自:http://blog.163.com/wangy_0223/blog/static/450146612012318113233218/ 示例代码的Github地址:https://github ...
- 理解、学习与使用Java中的Optional
从Java8 引入的一个很有趣的特性是Optional类.Optional类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异 ...
- linux学习笔记30--命令at和crontab
在windows系统中,windows提供了计划任务这一功能,在控制面板 -> 性能与维护 -> 任务计划, 它的功能就是安排自动运行的任务. 通过'添加任务计划'的一步步引导,则可建立一 ...
- redis-trib构建集群
https://blog.csdn.net/qq_35946990/article/details/78957618
- ffmpeg 日志系统av_log()
一般使用Error, Warning, Debug3个级别即可(见下面的颜色).AV_LOG_QUIET 核心函数只有一个:av_log().使用av_log()在控制台输出日志的效果如下图所示. a ...
- CentOS安装python setuptools and pip
安装setup-tools wget https://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg --n ...
- Tomcat nginx log日志按天分割切割
利用 Linux 自带的 logrotate 工具来实现按天切割日志.下方已 centos 7 系统为例来实践讲解. 原理 Logrotate是基于CRON来运行的,其脚本是/etc/cron.dai ...