数据结构——顺序表

简介: 数据结构——顺序表

顺序表的原理

顺序表是简单的一种线性结构,逻辑上相邻的数据在计算机内的存储位置也是相邻的,可以

快速定位第几个元素,中间不允许有空值,插入、删除时需要移动大量元素。

顺序表的三个要素:


elems 记录存储位置的基地址

分配一段连续的存储空间 size

length 记录实际的元素个数,即顺序表的长度


c3900cdf55b44c7388de646130ac99a8.png


结构体定义

#define     MAX_SIZE 100 struct _SqList{


                ElemType    *elems;            // 顺序表的基地址


                int length; // 顺序表的长度


                int size; // 顺序表总的空间大小


}


顺序表的算法实现(顺序表的初始化)

#define MAX_SIZE 100
typedef struct{
int *elems; // 顺序表的基地址 int length; // 顺序表的长度 int size;  // 顺序表的空间
}SqList;
bool initList(SqList &L) //构造一个空的顺序表L
{
L.elems=new int[MAX_SIZE];        //为顺序表分配Maxsize个空间
if(!L.elems) return false; //存储分配失败
L.length=0;                     //空表长度为0
L.size = MAX_SIZE; return true;
}

b125c44ee304473bb422e5d280f97f9b.png


顺序表增加元素

bool listAppend(SqList &L, int e)
{ if(L.length==MAX_SIZE) return false; //存储空间已满
L.elems[L.length] = e;
L.length++;                 //表长增1
return true;
}


065453d76cab4539941f0aa5906caab4.png


顺序表插入元素

bool listInsert(SqList &L,int i, int e)
{ if(i<0 || i>=L.length)return false; //i值不合法 if(L.length==MAX_SIZE) return false; //存储空间已满
for(int j=L.length-1; j>=i; j--){
L.elems[j+1]=L.elems[j];//从最后一个元素开始后移,直到第i个元素后移
}
L.elems[i]=e; //将新元素e放入第i个位置 L.length++; //表长增1
return true;
}

8fc7cb67968144daab01955e3c28de2d.png

顺序表删除元素

bool listDelete(SqList &L,int i)
{ if(i<0 || i>=L.length) return false; //不合法
if(i == L.length-1){//删除最后一个元素,直接删除
L.length--; return true;
}
for (int j=i; j<L.length-1; j++){
L.elems[j] =L.elems[j+1]; //被删除元素之后的元素前移
}
L.length--; return true;
}


aae85098a40b4dfe8342b2d045b4caeb.png


顺序表销毁

void destroyList(SqList &L)
{ if (L.elems) delete []L.elems;//释放存储空间
L.length = 0;
L.size = 0; }


完整代码实现

#include <iostream>
#include <Windows.h>
using namespace std;
#define MAX_SIZE  100
typedef struct
{
  int* elems;
  int length;
  int size;
}SqList;
bool initList(SqList& L)
{
  L.elems = new int[MAX_SIZE];
  if (!L.elems)
  {
    return false;
  }
  L.size = MAX_SIZE;
  L.length = 0;
  return true;
}
bool AppendList(SqList& L, int z)
{
  if (L.length == L.size)
  {
    return false;
  }
  L.elems[L.length] = z;
  L.length += 1;
  return true;
}
bool insertList(SqList& L, int z, int i)
{
  if (L.length == L.size || i<0)
  {
    return false;
  }
  //插入的数在顺序表末尾
  if (L.length - 1 == i)
  {
    L.elems[L.length] = z;
    L.length += 1;
    return true;
  }
  //插入的数没在顺序表末尾
  for (int j = L.length - 1; i <= j; j--)
  {
    L.elems[j + 1] = L.elems[j];
  }
  L.elems[i] = z;
  L.length += 1;
  return true;
}
bool deleteList(SqList& L, int z, int i)
{
  if (L.elems==NULL)
  {
    cout << "数据为空!" << endl;
    return false;
  }
  for (int j = i; j <= L.length-2 ; j++)
  {
    L.elems[j] = L.elems[j + 1];
  }
  L.length = L.length - 1;
  return true;
}
bool destroyList(SqList& L)
{
  if (L.elems)
  {
    delete[]L.elems;
  }
  L.length = 0;
  L.size = 0;
  return true;
}
void printList(SqList& L)
{
  cout << "数据有:" << endl;
  for (int i = 0; i < L.length; i++)
  {
    cout << L.elems[i] << " ";
  }
}
int main1(void)
{
  SqList list;
  int x = 0;
  //初始化顺序表
  initList(list);
  //追加数据
  for (int i = 0; i < 10; i++)
  {
    AppendList(list, i);
  }
  printList(list);
  cout << endl;
  cout << "请输入你要插入的数据和对应位置:";
  insertList(list, 9, 3);
  printList(list);
  cout << "请输入你要删除的数据和对应位置:";
  deleteList(list, 9, 3);
  printList(list);
  //销毁顺序表
  cout << "请销毁顺序表:";
  destroyList(list);
  system("pause");
  return 0;
}


顺序表的企业级应用案例:


高并发 WEB 服务器中顺序表的应用


高性能的 web 服务器 Squid 每秒可处理上万并发的请求,从网络连接到服务器的客户端与服务器端在交互时会保持一种会话(和电话通话的场景类似)。服务器端为了管理好所有的客户端连接,给每个连接都编了一个唯一的整数编号,叫做文件句柄,简称 fd.


4223dd4b713744b981affb7dfb9b7038.png

为了防止某些恶意连接消耗系统资源,当某个客户端连接超时(在设定的一定时

间内没有发送数据)时,服务器就需要关闭这些客户端的连接具体


实现方案:


1. 当有新的请求连到服务器时,如果经过服务器频率限制模块判断,貌似恶意连接,则使用顺序表来保存此连接的超时数据,超时值使用时间戳来表示,时间戳是指格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒(相当于北京时间 1970 年 01 月 01 日


08 时 00 分 00 秒)起至现在的总秒数,其结构体定义如下:


typedef struct {


       int fd ;


       time_t timeout; // 使用超时时刻的时间戳表示


}ConnTimeout;


2. 服务器程序每隔一秒钟扫描一次所有的连接,检查是否超时,如果存在超时的


连接,就关闭连接,结束服务,同时将顺序表中的记录清除!


代码如下:

webServer.cpp

#include <iostream>
#include <time.h>
#include <Windows.h>
#include "webServer.h"
using namespace std;
static void checkTimeouts(TimeoutSqList& list, time_t now);
int main(void)
{
  time_t now, end;
  time_t last_timeout;
  TimeoutSqList list;
  time(&now);
  end = now + 60;
  last_timeout = now;
  initList(list);
  //1.模拟频率限制模块通过判断分析,增加恶意连接到顺序表中
  for (int i = 0; i < 10; i++)
  {
    ConnTimeout e;
    e.fd = i;
    e.timeout = now + 5 + 2 * i; 
    AppendList(list, e);
  }
  printList(list);
  do
  {
    if (last_timeout + 0.999 < now)
    {
      checkTimeouts(list, now);//检查超时的连接
      last_timeout = now;
    }
    Sleep(10);//防止cpu空转
    time(&now);
  } while (now < end);
  /*time_t now;
  time(&now);
  cout << "当前的时间戳 - timestamp:" << now << endl;
  Sleep(2000);
  time(&now);
  cout << "两秒以后的时间戳 - timestamp:" << now << endl;*/
  system("pause");
  return 0;
}
void checkTimeouts(TimeoutSqList& list, time_t now)
{
  int fd, i;
  cout << "检查超时fd……\n";
  for (i = 0; i < list.length; i++)
  {
    if (list.elems[i].timeout > now)
    {
      continue;
    }
    //超时,清理连接
    fd = list.elems[i].fd;
    //关闭连接
    printf("连接[fd=%d] 已经超时,关闭连接!\n", fd);
    //删除顺序表中的元素
    i--;
    deleteList(list, i);
  }
}


TimeoutSqList.cpp

#include "webServer.h"
#include <iostream>
#include <Windows.h>
using namespace std;
bool initList(TimeoutSqList& L)
{
  L.elems = new ConnTimeout[MAX_SIZE];
  if (!L.elems)
  {
    return false;
  }
  L.size = MAX_SIZE;
  L.length = 0;
  return true;
}
bool AppendList(TimeoutSqList& L, ConnTimeout z)
{
  if (L.length == L.size)
  {
    return false;
  }
  L.elems[L.length] = z;
  L.length += 1;
  return true;
}
bool insertList(TimeoutSqList& L, ConnTimeout z, int i)
{
  if (L.length == L.size || i < 0)
  {
    return false;
  }
  //插入的数在顺序表末尾
  if (L.length - 1 == i)
  {
    L.elems[L.length] = z;
    L.length += 1;
    return true;
  }
  //插入的数没在顺序表末尾
  for (int j = L.length - 1; i <= j; j--)
  {
    L.elems[j + 1] = L.elems[j];
  }
  L.elems[i] = z;
  L.length += 1;
  return true;
}
bool deleteList(TimeoutSqList& L, int i)
{
  if (L.elems == NULL)
  {
    cout << "数据为空!" << endl;
    return false;
  }
  for (int j = i; j <= L.length - 2; j++)
  {
    L.elems[j] = L.elems[j + 1];
  }
  L.length = L.length - 1;
  return true;
}
bool destroyList(TimeoutSqList& L)
{
  if (L.elems)
  {
    delete[]L.elems;
  }
  L.length = 0;
  L.size = 0;
  return true;
}
void printList(TimeoutSqList& L)
{
  cout << "当前:" << L.size << ",已保存元素的个数 length:" << L.length << endl;
  for (int i = 0; i < L.length; i++)
  {
    cout << "fd:" << L.elems[i].fd << ",timeout:" << L.elems[i].timeout << endl;
  }
}


webServer.h

#ifndef _WEB_SERVER_H_
#define _WEB_SERVER_H_
#include <time.h>
#define MAX_SIZE 100
typedef struct
{
  int fd;
  time_t timeout;//使用超时时刻的时间戳表示
}ConnTimeout;
typedef struct
{
  ConnTimeout* elems; //顺序表的基地址
  int length;     //顺序表的长度
  int size;     //顺序表的大小
}TimeoutSqList;
//顺序表的接口
bool initList(TimeoutSqList& L);
bool AppendList(TimeoutSqList& L, ConnTimeout z);
bool deleteList(TimeoutSqList& L, int i);
bool destroyList(TimeoutSqList& L);
void printList(TimeoutSqList& L);
#endif


相关文章
|
2月前
|
存储 编译器 C语言
数据结构-顺序表详解(看这篇就足够了,哈哈哈)
数据结构-顺序表详解(看这篇就足够了,哈哈哈)
59 2
|
1月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
1月前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
72 3
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
2月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
39 6
|
2月前
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
27 3
|
2月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
32 2
|
2月前
|
存储
【数据结构】线性表和顺序表
【数据结构】线性表和顺序表
23 1
|
2月前
|
存储 算法 索引
【数据结构】——顺序表
【数据结构】——顺序表
|
2月前
|
存储
数据结构1——顺序表
数据结构1——顺序表
19 1