<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, 0, sizeof(fifo));
fifo_ptr->write_ptr = 0;
fifo_ptr->read_ptr = 0;
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) == -1){
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 = 0;

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) == 0){
fifo_ptr->flag = EMPTY;
}
//printf("read_ptr = %d \n", fifo_ptr->read_ptr);
return data;
}else{
printf("fifo is empty, read invalide\n");
return -1;
}

return -1;
}

  我们可以写一个测试代码来测试它的性能:


#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(1){
pthread_mutex_lock(&lock_fifo);
fifo_in(myfifo, 1);
pthread_mutex_unlock(&lock_fifo);
printf("producer1 put 1 into myfifo\n");
usleep(2000000);
}
return((void*)0);
}

void * producer_thread2(void *pin){
pin = NULL;
while(1){
pthread_mutex_lock(&lock_fifo);
fifo_in(myfifo, 2);
pthread_mutex_unlock(&lock_fifo);
printf("producer2 put 2 into myfifo\n");
usleep(1500000);
}
return((void*)0);
}

void * consumer_thread1(void *pin){
int require = 0;
pin = NULL;

while(1){
pthread_mutex_lock(&lock_fifo);
require = fifo_out(myfifo);
pthread_mutex_unlock(&lock_fifo);
printf(" consumer1 get %d form myfifo\n", require);
usleep(1000000);
}
return((void*)0);
}

void * consumer_thread2(void *pin){
int require = 0;
pin = NULL;

while(1){
pthread_mutex_lock(&lock_fifo);
require = fifo_out(myfifo);
pthread_mutex_unlock(&lock_fifo);
printf(" consumer2 get %d form myfifo\n", require);
usleep(1000000);
}
return((void*)0);
}

void keyboard_exit(int signo){
printf("exit by keyboard \n");
fifo_destroy(myfifo);
_exit(0);
}

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, 0);
pthread_create(&th_producer2, NULL, producer_thread2, 0);
pthread_create(&th_consumer1, NULL, consumer_thread1, 0);
pthread_create(&th_consumer2, NULL, consumer_thread2, 0);

pthread_join(th_producer1, &ret);
pthread_join(th_producer2, &ret);
pthread_join(th_consumer1, &ret);
pthread_join(th_consumer2, &ret);

while(1){
printf("thread error\n");
}
return 1;
}

  写一个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 = 1
producer1 put 1 into myfifo
write_ptr = 2
producer2 put 2 into myfifo
read_ptr = 1
consumer1 get 1 form myfifo
read_ptr = 2
consumer2 get 2 form myfifo
fifo is empty, read invalide
consumer1 get -1 form myfifo
fifo is empty, read invalide
consumer2 get -1 form myfifo
write_ptr = 3
producer2 put 2 into myfifo
write_ptr = 4
producer1 put 1 into myfifo
read_ptr = 3
consumer1 get 2 form myfifo
read_ptr = 4
consumer2 get 1 form myfifo
write_ptr = 5
producer2 put 2 into myfifo
read_ptr = 5
。。。。
。。。。
^Cexit by keyboard
destroy fifo

时间: 2024-08-08 10:26:41

<2014 05 16> 线性表、栈与队列——一个环形队列的C语言实现的相关文章

队列和环形队列

队列 队列的一个使用场景 银行排队的案例: 银行柜台都有人办理业务时,后面来的人,就要进行抽号排队(先来的人号肯定在前面). 有人业务办理完后,柜台会进行叫号(从最前面的号开始叫). 队列介绍 队列是一个有序列表,可以用数组或者链表来实现. 遵循先入先出的原则.即:先存入队列的数据,要先取出.后存入的数据要后取出. 示意图:(使用数组模拟队列示意图) 数组模拟队列思路 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如上图, 其中maxSize是该队列的最大容量. 因为队列

5 线性表-栈-链式存储

头大-- 栈是一种功能受限的线性表 1.基本功能实现 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<iostream> 4 using namespace std; 5 #define TRUE 1 6 #define FALSE 0 7 #define OK 1 8 #define ERROR 0 9 #define OVERFLOW -2 10 #define STACK_INIT_SIZE 100//存储空

数据结构和算法学习总结04 线性表---栈

栈 栈(Stack)是特殊的线性表,是只允许在一端进行插入和删除的线性表. 允许插入和删除的叫栈顶,反之则是栈底. 栈的插入称为进栈,删除称为出栈. 特性是:后进先出,所以栈也叫后进先出表,简称LIFO表(Last In First Out). 因为栈是线性表,所以也有顺序表和链表两种形式,一般我们常用顺序表. 从代码中可以看出:与顺序表相比实际上就是插入和删除操作发生了改变. #include <iostream> using namespace std; const int Stack_S

数据结构-线性表-栈

栈:后进先出(LIFO) last in first out栈是一种特殊的线性表,只能在线性表的一端进行操作.栈顶 top栈底 bottom 实现方式:顺序结构实现,线性结构实现 链式存储实现 LinkStack.h #ifndef _LINKSTACK_H_ #define _LINKSTACK_H_ typedef void LinkStack; LinkStack* LinkStack_Create(); void LinkStack_Destroy(LinkStack* stack);

2.线性表——栈

1.什么是栈 [1]. 栈是一种只能在一端进行插入和删除操作的线性表:插入:入栈(push):删除:出栈(pop): [2]. 栈是按照“先进后出”(Last In First Out, LIFO)的原则存储数据: 栈顶(Top):允许删除和插入: 栈底(Botton) : [3]. 栈的分类: 静态栈:其核心是数组,类似于一个连续内存的数组,需要提前确定好栈的大小: 动态栈:其核心是链表,内存够用的前提下,可以无穷大,不连续: [4]. 栈的表示: 1.1 栈的表示 2. 栈的基本操作 [1]

2 限定性线性表——栈与队列

1 栈与队列     1.1 包含min函数的栈 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数 在该栈中,调用min.push和pop方法 要求时间复杂度均为O(1) 算法思想: 要求时间复杂度均为 O(1),增加辅助空间实现,即增加一个辅助栈存储min值 例如:data 中依次入栈 5, 4, 3, 8, 10, 11, 12, 1, 则 min 中依次入栈 5, 4, 3,no,no, no, no, 1. no 代表此次不如栈,如果入栈的元素小于等于 min 中的栈

6 线性表-栈-顺序存储

自己简直是强迫症晚期,上次因为对访问结构体成员该用什么方法困惑了很久,导致没把顺序存储的捣鼓出来(明明比链式的要好写) 今天花了个20分钟调好了 因为今天比较晚,赶时间就没给类型起别名用ElemType写,直接用了int类型.需要的话可以自行更改. 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<iostream> 4 using namespace std; 5 #define maxsize 50 6 /*顺序

线性表——栈

package Algorithm; /**  * 栈   * 1.先进后出  * 2.对插入/删除操作的"限定",只能在表的一端进行插入删除操作  * 3.遍历数据速度不同,最先放入最后取出,遍历数据需要开辟临时空间  */ public class MyStack { private Object[] data; private int size; private int top; public MyStack() { super(); this.data = new Object

7 线性表-栈-顺序存储的拓展-迎面增长的存储方式

描述:设有两个栈,S1和S2,都采用顺序栈的存储方式.两个栈共享一个存储区:[0,--maxsize-1]目的:可以尽量利用空间,减少溢出的可能,采用栈顶相向.迎面增长的存储方式 PS:要注意判断栈满栈空的检查 #include<stdio.h> #include<stdlib.h> #include<iostream> using namespace std; #define maxsize 100 /*栈结构的定义*/ typedef struct { int st