【Data】队列和串

一、队列的定义:

队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端删除元素。象日常生活中的排队,最早入队的最早离开。

在队列中,允许插入的的一端叫 队尾 ,允许删除的一端则称为 队头

抽象数据类型队列:

ADT Queue{

数据对象: D={ai| ai(-ElemSet,i=1,2,...,n,n>=0}

数据关系: R1={<ai-1,ai> | ai-1,ai(- D,i=2,...,n}

基本操作:

InitQueue(&Q) 构造一个空队列Q

Destroyqueue(&Q) 队列Q存在则销毁Q

ClearQueue(&Q) 队列Q存在则将Q清为空队列

QueueEmpty(Q) 队列Q存在,若Q为空队列则返回TRUE,否则返回FALSE

QueueLenght(Q) 队列Q存在,返回Q的元素个数,即队列的长度

GetHead(Q,&e) Q为非空队列,用e返回Q的队头元素

EnQueue(&Q,e) 队列Q存在,插入元素e为Q的队尾元素

DeQueue(&Q,&e) Q为非空队列,删除Q的队头元素,并用e返回其值

QueueTraverse(Q,vivsit()) Q存在且非空,从队头到队尾,依次对Q的每个数据元素调用函数visit()。一旦visit()失败,则操作失败

}ADT Queue

二、链队列
           ——队列的链式表示和实现
用链表表示的队列简称为 链队列 。一个链队列显然需要两个分别指示队头和队尾的指针。



//存储表示

typedef struct QNode{

QElemType data;

struct QNode *next;

}QNode,*QueuePtr;

typedef struct{

QueuePtr front;

QueuePtr rear;

}LinkQueue;

//操作的实现

Status InitQueue(LinkQueue &Q) {

//构造一个空队列Q

Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));

if(!Q.front)exit(OVERFLOW);

Q.front->next=NULL;

return OK;}

Status Destroyqueue(LinkQueue &Q) {

//队列Q存在则销毁Q

while(Q.front){

Q.rear=Q.front->next;

free(Q.front);

Q.front=Q.rear;

}

return OK;}

Status EnQueue(LinkQueue &Q,QElemType e) {

//队列Q存在,插入元素e为Q的队尾元素

p=(QueuePtr)malloc(sizeof(QNode));

if(!p) exit(OVERFLOW);

p->data=e;p->next=NULL;

Q.rear->next=p;

Q.rear=p;

return OK;}

Status DeQueue(LinkQueue &Q,QElemType &e) {

//Q为非空队列,删除Q的队头元素,并用e返回其值

if(Q.front==Q.rear)return ERROR;

p=Q.front->next;

e=p->data;

Q.front->next=p->next;

if(Q.rear==p)Q.rear=Q.front;

free(p);

return OK;}


三、串定义

(或字符串),是由零个或多个字符组成的有限序列。一般记为:

s='a1a2...an'(n>=0)

其中s是串的名,用单引号括起来的字符序列是串的值;串中字符的数目n称为串的长度。零个字符的串称为空串,它的长度为零。

串中任意个连续的字符组成的子序列称为该串的子串。包含子串的串相应地称为主串。子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。

例:a='BEI',b='JING',c='BEIJING',d='BEI JING'

串长分别为 3,4,7,8,且a,b都是c,d的子串。
称两个串是相等的,当且仅当这两个串的值相等。

四、串的抽象数据类型的定义:

ADT String{

数据对象:D={ai|ai(-CharacterSet,i=1,2,...,n,n>=0}

数据关系:R1={<ai-1,ai>|ai-1,ai(-D,i=2,...,n}

基本操作:

StrAssign(&T,chars)//chars是字符常量。生成一个其值等于chars的串T。

StrCopy(&T,S)//S存在则由串S复制得串T

StrEmpty(S)//S存在,若S为空串,返回真否则返回假

StrCompare(S,T)//S和T存在,若S>T,则返回值大于0,若S=T,则返回值=0,若S<T,则返回值<0

StrLength(S)//S存在返回S的元素个数称为串的长度.

ClearString(&S)//S存在将S清为空串

Concat(&T,S1,S2)//S1和S2存在用T返回由S1和S2联接而成的新串

SubString(&Sub,S,pos,len) //  S存在, 将串S中从第pos个字符开始长度为len的字符序列复制到 串Sub。 1<=pos<=StrLength(S)且0<=len<=StrLength(S)-pos+1

Index(S,T,pos)//S和T存在,T是非空,1<=pos<=StrLength(S),若主串S中存在和串T值相同的子串,则返回它在主串S中第pos个字符之后第一次出现的位置,否则函数值为0

Replace(&S,T,V)//S,T和V存在,T是非空串,用V替换主串S中出现的所有与T相等的不重叠的子串

StrInsert(&S,pos,T)//串S和T存在,1<=pos<=StrLength(S)+1,在串S的第pos个字符之前插入串T

StrDelete(&S,pos,len)//S存在,1<=pos<=StrLength(S)-len+1从串中删除第pos个字符起长度为len的子串

DestroyString(&S)//S存在,则串S被销毁

}ADT String

抓狂肿么这么多操作!!!

下一篇继续讲好了,串的几种实现方法



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
口通信中,使用环形队列可以很好地处理收发数据的缓存和流控。 环形队列是一种特殊的队列,它的存储空间是环形的,即队列的尾部指向队列的开头,可以循环利用队列的存储空间。在口通信中,可以将收到的数据放入队列中,然后再从队列中取出数据发送出去。 以下是使用环形队列实现口收发的示例代码: ```c++ #include <iostream> #include <windows.h> #define QUEUE_SIZE 1024 class CircularQueue { public: CircularQueue() { head_ = 0; tail_ = 0; size_ = QUEUE_SIZE; buffer_ = new char[size_]; } ~CircularQueue() { delete[] buffer_; } bool is_empty() const { return head_ == tail_; } bool is_full() const { return (tail_ + 1) % size_ == head_; } int size() const { return (tail_ - head_ + size_) % size_; } bool push(char data) { if (is_full()) { return false; } else { buffer_[tail_] = data; tail_ = (tail_ + 1) % size_; return true; } } bool pop(char& data) { if (is_empty()) { return false; } else { data = buffer_[head_]; head_ = (head_ + 1) % size_; return true; } } private: char* buffer_; int head_; int tail_; int size_; }; int main() { HANDLE hcom = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hcom == INVALID_HANDLE_VALUE) { std::cerr << "failed to open COM1\n"; return 1; } DCB dcb = { 0 }; dcb.DCBlength = sizeof(DCB); if (!GetCommState(hcom, &dcb)) { std::cerr << "failed to get comm state\n"; CloseHandle(hcom); return 1; } dcb.BaudRate = 9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(hcom, &dcb)) { std::cerr << "failed to set comm state\n"; CloseHandle(hcom); return 1; } COMMTIMEOUTS timeouts = { 0 }; timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; timeouts.ReadTotalTimeoutConstant = 1000; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 1000; if (!SetCommTimeouts(hcom, &timeouts)) { std::cerr << "failed to set comm timeouts\n"; CloseHandle(hcom); return 1; } CircularQueue queue; while (true) { char buf[1024]; DWORD nread = 0; if (ReadFile(hcom, buf, sizeof(buf), &nread, NULL)) { for (DWORD i = 0; i < nread; i++) { if (!queue.push(buf[i])) { std::cerr << "queue full\n"; } } } else { std::cerr << "read error\n"; } char data; while (queue.pop(data)) { DWORD nwrite = 0; if (!WriteFile(hcom, &data, 1, &nwrite, NULL)) { std::cerr << "write error\n"; } } } CloseHandle(hcom); return 0; } ``` 该代码使用 Windows API 实现口通信,使用 CircularQueue 类实现环形队列。在主循环中,不断从口读取数据,并将数据放入环形队列中;同时,从环形队列中读取数据,并将数据发送到口中。 需要注意的是,在实际应用中,可能需要更加完善的错误处理和流控机制,以确保数据的正确传输。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值