栈与队列都是具有特殊存取方式的线性表,栈属于先进后出(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语言实现的更多相关文章

  1. [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)

    循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...

  2. k:特殊的线性表—栈

    栈(Stack):  栈是一种特殊的线性表,栈中的数据元素以及数据元素之间的逻辑关系和线性表相同,两者之间的差别在于:线性表的插入和删除操作可以在表的任意位置进行,而栈的插入和删除操作只允许在表的尾端 ...

  3. 数据结构-线性表的链式存储相关算法(C语言实现)

    链表的简单介绍 为什么需要线性链表 当然是为了克服顺序表的缺点,在顺序表中,做插入和删除操作时,需要大量的移动元素,导致效率下降. 线性链表的分类 按照链接方式: 按照实现角度: 线性链表的创建和简单 ...

  4. 队列(Queue)--环形队列、优先队列和双向队列

    1. 队列概述 队列和堆栈都是有序列表,属于抽象型数据类型(ADT),所有加入和删除的动作都发生在不同的两端,并符合First In, First Out(先进先出)的特性. 特性: ·FIFO ·拥 ...

  5. Java 单向队列及环形队列

    队列的特点 1.可以使用数组和链表两种方式来实现. 2.遵循先入先出(FIFO)的规则,即先进入的数据先出. 3.属于有序列表. 图解实现过程: ​ 1.定义一个固定长度的数组,长度为maxSize. ...

  6. c# 写着玩的,两个Task并发,一个写队列一个读队列的异常情况

    class Program { class TestEnqueue { static Queue<string> str = new Queue<string>(); publ ...

  7. Java数据结构之线性表(2)

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  8. java线性表学习笔记(一)

    线性表是一种按顺序储存数据是的常用结构,大多数的线性表都支持以下的典型操作: 从线性表提取插入删除一个数据: 找出线性表中的某一个元素: 找出线性表中的元素: 确定线性表中是否包含某一个元素,确定线性 ...

  9. 线性表结构的Java实现

    一.线性表的抽象数据类型表述 线性表的结构简单,长度允许动态增长或搜索:可以对线性表中的任何数据元素进行访问和查找:允许进行数据的插入和删除操作:求线性表中的指定数据的前驱和后继:合并线性表以及拆分线 ...

随机推荐

  1. Request介绍及演示样例 PART1

    Request在ServletAPI的规范连接地址http://blog.csdn.net/zghwaicsdn/article/details/51035146 HTTP简介 URL是浏览器寻找信息 ...

  2. apache与和mysql重启命令

    修改linux服务器的http配置之后,必须重启Apache服务. 命令为: /etc/rc.d/init.d/httpd restart chown -R mysql:mysql 目录名 改变文件属 ...

  3. MVC页面跳转,路径重复的问题

    window.location.replace("../Home/xxx") 这是js路径跳转的示范,如果普通超链接也一样 前面加一个../

  4. Java创建多线程的三种方法

    Java多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...

  5. C# 冒泡排序

    class Program { static void swap( ref int atemp, ref int btemp)//注意ref的使用 { int temp = atemp; atemp ...

  6. python学习之urlparse()

    urlparse(url, scheme='', allow_fragments=True) <scheme>://<netloc>/<path>;<para ...

  7. iOS之设置用户头像的圆角

    1. 显示用户头像用UIImageView实现,添加默认图片后效果如下图所示,头像显示为矩形图片. 代码实现: // ViewController.m // SetUserImage // // Cr ...

  8. SSH初体验系列--Hibernate--1--环境配置及demo

    最近在学hibernate,常见的教程都是搭配mysql,因为公司本地电脑用的是pg,所以就尝试着做个pg的小demo. 自己也是边学边写,只当是加深印象.话不多说,直接开始; 一) 准备工作; 1) ...

  9. 2017 ACM区域赛(西安) 参赛流水账

    day 0: 周五, 鸽了概统课,早上和紫金港的几位小伙伴一起打车去萧山机场,从咸阳机场到西北工业大学坐了五十多个站的公交车,感觉身体被掏空.晚上在宾馆本来打算补之前训练的一个题,想想还是先花个十来分 ...

  10. Java WEB 之页面间传递特殊字符

    本文是学习网络上的文章时的总结以及自己的一点实践.感谢大家无私的分享. 昨天在做项目的时候,有一个页面间传递特殊字符的需求,查了一些资料.如今将自己的经验写出来. 首先.在前台编码 var fckPu ...