第一章、线性表

 第一章   线性表

 一、线性表的基本概念

      线性表(List):零个或多个数据元素的有限序列。

      用数学语言来进行定义:
          若将线性表记为(a1,...,ai-1,ai,ai+1,...,an),则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。当i=1,2,...,n-1时,ai有且仅有一个直接后继,当 i=2,3,...,n时,ai有且仅有一个直接前驱。

      线性表元素的个数n (n>=0)定义为线性表的长度,当n=0时,成为空表。

       在非空表中的每个数据元素都有一个确定的位置,如a1是第一个元素,an是最后一个数据元素,ai是第i个数据元素,称i为数据元素ai在线性表中的位序。

二、线性表的顺序存储结构


       线性表的物理存储结构分为两种:
              1. 线性表的顺序存储结构:指的是用一段地址连续的存储单元依次存储线性表的数据元素。(数组)
                  优点:无须为表示表中元素之间的逻辑关系而增加额外的存储空间
                             可以快速地存取表中任一位置的元素
                  缺点:插入和删除操作需要移动大量元素
                             当线性表长度变化比较大时,难以确定存储空间的容量
                             造成存储空间的“碎片”

              2. 线性表的链式存储结构:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的,这就意味着,这些数据元素可以存储在内存未被占用任意位置。
                   

        线性表的顺序存储结构代码:
        #define  MAXSIZE 20                       /*存储空间初始分配量*/
        typedef int ElemType;                      /*ElemType 类型根据实际情况而定,这里假设为int*/
        typedef   struct{
               ElemType data[MAXSIZE];       /*数组存储数据元素,最大值为MAXSIZE*/
               int length;                                  /*线性表当前长度*/
        }SqList;

       数据长度与线性表长度区别
             数组的长度 :存放线性表的存储空间的长度,存储分配后这个量是一般不变的。
             线性表的长度是:线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是变化的。
       
       地址的计算方法:
              假设一个数据元素占用的是C个存储单元,那么对于第i个数据元素ai的存储位置可以有a1推算得出:
               LOC(ai)=LOC(a1)+(i-1)*c

       通过这个公式,你可以算出线性表中任意位置的地址,且时间相等,是个常数,所以它的存取时间复杂度O(1)。
       我们把具有这一特点的存储结构称为“随即存取结构”。

       基本操作算法:
              #define OK 1
              #define ERROR 0
              #define TRUE 1
              #define FLASE 0
              typedef  int  Status;
 
             1. 获取元素操作
                      Status  GetElem(SqList L, int i, ElemType *e){
                             
                            if(L.length == 0 || i<1 || i>L.length)                           
                                 return ERROR;
                            *e = L.data[i-1];       //数组的下标从
                            return OK;
                      }
              2. 插入操作
                      Status  ListInsert(SqList *L,int i,ElemType e){
                            
                           int  k;
                           if(L->length == MAXSIZE)       //顺序线性表已经满
                               return ERROR;
                           if(i<1 || i>L->length+1)            //当i 不在范围内时
                               return ERROR;
                           if(i<=L->length){
                               //为什么都有减1,这是因为数组的下标是从0开始计数的,所以要想插入到i位置,实际是i-1
                               for(k=L->Length-1;k>i-1;k--){    //从最后一个元素开始遍历
                                         L->data[k+1] = L->data[k];    //往后错一个位置
                               }
                               L->data[i-1] = e;
                               L->length++;
                               return OK;
                           }
                      }

                     3. 删除操作
                     
                          Status ListDelete(SqList *L, int i, ElemType *e){
                                 
                                int k;
                                if(L->length == 0)
                                    return ERROR;
                                if(i<1 || i>L->length)  
                                    return ERROR;

                                *e = L->data[i-1];
                                if(i<L->length){
                                   for(k=i; k<L->length;k++)   //从删除的位置开始,往前移动
                                       L->data[k-1] = L->data[k]
                                }
                                L->length--;
                                return OK;

                          }
                                               

三、线性表的链式存储结构


           在顺序存储结构的线性表中,每个数据只需要数据元素信息就可以了。现在链式存储结构中,除了要存储数据元素信息外,还要存储它的后继元素的存储地址。

           把存储数据元素信息的域称为数据域
           把存储直接后继位置的域称为指针域 ,指针域存储的信息称做指针或链
           这两部分信息组成数据元素ai的存储映像,成为结点(Node)
           n个节点(ai的存储映像)链结成一个链表,即为线性表(a1,a2,...,an)的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表。
          链表中第一个节点的存储位置叫做头指针
           在单链表的第一个结点前附设一个节点,称为头结点。头结点的数据域可以不存储任何信息,也可以存储线性表的长度等附加信息,头结点的指针域存储指向第一个节点的指针。

           头指针与头结点的异同:
                     头指针
                           头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。
                           头指针具有标识作用,所以常用头指针冠以链表的名字。
                           无论链表是否为空,头指针均不为空,头指针是链表的必要元素。

                     头节点
                           头结点是为了操作的统一和方便而设立的,放在第一元素的结点之前,其数据域一般无意义(也可存放链表的长度)
                           有了头结点,对在第一元素结点前插入结点和删除第一结点,其操作与其它结点的操作就统一了。
                           头结点不一定是链表必须要素。

            用C语言描述线性表的单链表存储结构
             typedef  struct  Node{
                   ElemType  data;
                   struce Node *next;
             } Node;
             typedef  struct  Node *LinkList;
             结点有存放数据元素的数据域和存放后继结点地址的指针域组成。
            
             单链表的读取:
                   //用e返回L中第i个数据元素的值
                  Status  GeteElem(LinkList  L, int i, ElemType *e){
                           int j;
                           LinkList p;                       // 声明一结点
                           p = L->next;                   //  让p指向链表L的第一个节点
                           j = 1;                              //   j为计数器
                           while(p && j<i){              //  p 不为空或者计数器j还没等于i时,循环继续
                                p = p->next;              //  让p指向下一个结点
                                ++j;
                           }
                           if(!p  || j>i)
                                 return ERROR;
                           *e = p->data;
                           return OK;
                   }

             单链表的插入:
                   // 在L中第i个位置之前插入新的数据元素e,L的长度加1
                  Status  ListInsert(LinkList *L, int i, ElemType e){
                          int  j;
                          LinkList p, s;
                          p = *L;
                          j  = 1;
                          while(p && j<i){
                               p = p->next;
                               ++j;
                          }
                          if(!p || j>i)
                               return ERROR;
                          s = (LinkList)malloc(sizeof(Node));      // 生成新结点
                          s->data = e;                                         //把要插入的数据信息存在新生成的S的数据域中
                          s->next = p->next;                               // 将p的后继结点赋值给s的后继
                          p->next = s;                                         //将s赋值给p的后继
                         return OK;
                  }

                  单链表的删除:
                   // 删除L的第i个数据元素,并用e返回值,L的长度减1
                   Status ListDelete(LinkList *L, int i, ElemType *e){
                         int j;
                         LinkList p,q;          // q 等于是个中间变量,用完后,要记得释放
                         p = *L;
                         j  = 1;
                         while(p->next && j<i){
                               p=p->next;
                               ++j;
                         }   // 经过循环查找,找出来的p是要产出节点的前驱节点
                         if(!(p->next) || j>i)
                               return ERROR;                             
                         q = p ->next;               // q就是所要删除的结点
                         p->next = q->next       // 将要删除的节点q的指针域赋值给q的前驱结点
                         *e = q->data;              // 将要删除结点q中的数据给*e
                         free(q);                       // 让系统回收此结点,释放内存
                         return OK;               
                   }

                   单链表的整表创建(头插法)
                    // 头插法:始终让新结点在第一位置。
                    // 随机产生n个元素的值,建立带表头结点的单链线性表L
                    void  CreateListHead(LinkList  *L, int n){
                           LinkList p;
                           int i;
                           srand(time(0));                                                   //初始化随机数种子
                           *L = (LinkList) malloc(sizeof(Node));                 
                           (*L)->next = NULL;
                            for(i=0;i<n;i++){
                               p = (LinkList)malloc(sizeof(Node));
                               p->data = rand()%100+1;
                               p->next = (*L)->next;                       //始终让新结点在第一位置
                               (*L)->next = p;                                  //插入表头
                            }
                    }

                  单链表的整表创建(尾插法)
                   //随机产生n个元素的值,建立带表头结点的单链线性表L
                   void CreateListTail(LinkList *L, int n){
                       LinkList p,r;
                       int i;
                       srand(time(0));
                       *L = (LinkList) malloc(sizeof(Node));                 // 为整个线性表
                       r = *L;
                       for(i=0;i<n;i++){
                           p = (Node*)malloc(sizeof(Node));                  //生成新结点       
                           p->data = rand()%100 + 1;         
                           p->next = p;                                                   //将表尾终端结点的指针指向新结点
                           r = p;                                                             //将当前的新结点定义为表尾终端结点,这样下一次
                                                                                               //循环时,p就成为了表尾。其实r就是中间变量
                       }
                       r->next = NULL;                                           
                   } 

                 单链表的整表删除
                 //初始条件:顺序线性表L已存在,操作结果:将L重复置为空表
                 Status ClearList(LinkList *L){
                         LinkList p,q;
                         p = (*L)->next;          //p指向第一个结点
                         while(p){                  // 没到表尾就执行
                              q = p->next;
                              free(p);
                              p = q;
                         }
                         (*L)->next = NULL;      //头结点指针域为空
                         return OK;               
                  }

                  待续。。。。。。,还有一些高级的东西没写。



                  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值