数据结构笔记--线性表(上)

来源:互联网 发布:关于网络犯罪的小说 编辑:程序博客网 时间:2024/05/18 23:57

2.0 线性表的定义与基本运算

线性结构 基本特点: 在* 同构 的N个数据元素的 非有限集 *

  • 存在唯一的一个被称作为“第一个” 的数据元素
  • 存在唯一的一个被称作为“最后一个” 的数据元素
  • 除第一个外,集合中的每个数据元素均只有一个直接前驱
  • 除最后一个外,集合中的每个数据元素均只有一个直接后继

故此,有线性表如下的定义 : (a 1 ,a 2 ,a 3 ,,a n ) 

 一个线性表是 n 个同构的数据元素的有限序列.

特征如下:

  • 元素是同构的,且不能出现缺项 (即:每对相邻的两元素之间的步长均是1)
  • 记元素个数 n 作表的长度.
    • 当 n = 0时,记作 空表
    • 当 n > i > 1 时,
      • a i a i1 ;a n+1  
      • 若表不是循环表,则 a 1 ,a n  无后继

2.1 线性表的逻辑结构

数据元素又称为 结点,其种类有:

  • 单值型元素 每个元素只有一个数据项(item)
  • 记录型元素 每个元素含有多个数据项.
    • 此时称每个数据项为结点的一个域
    • 其中唯一标识一个结点的域的组合(一个或多个域) 被称为关键字

2.2 线性表的存储结构

2.2.1 顺序表(线性表的顺序存储结构)

顺序表 :把线性表的结点按逻辑结构依次存放在一组地址连续的存储单元里.
顺序表的优点:

  • 逻辑相邻,物理相邻(两者顺序是一致的)
  • 存储空间使用紧凑
  • 可以随机存取任一元素
    数据元素之间的关系是以元素在计算机内物理位置相邻来体现
    相应的有如下类似的存储位置的关系表达式
    LOC(a i )=LOC(a i1 )+L 
    LOC(a n )=LOC(a i )+(ni)L 

    其中

    • L 每个元素占用的存储单元
    • LOC(a i  ) 线性表第 i 个元素的地址

顺序表的缺点:

  1. 插入,删除 操作需要移动大量的元素
  2. 表容量难以扩容
  3. 预先分配空间需按最大空间分配,利用不充分

    note: 可以按照一定策略重新分配自动扩容,以规避掉缺点 2 和 3
    详情看下面的实现 enlargeSize()

2.2.2 顺序表的基本操作与实现

基本操作:

  • 创建
  • 赋值
  • 查找
  • 修改
  • 插入
  • 删除
  • 求长度

顺序表的C++实现

#include <stdio.h>   // for printf#include <stdlib.h>  // for calloc,free#include <string.h>  // for memmove#define SEQLIST_DEFAULT_SIZE 10///说明 : T 必须支持[]操作的复合类型,或者是基本类型template<typename T>struct SeqList {public:    SeqList(int size=SEQLIST_DEFAULT_SIZE) {        init(size);    }    bool delete(int idxDelete,T* saveOut=NULL){        //顺序表不为空,并且 idxDelete 在合理范围内        if(curSize && idxDelete>=0&& idxDelete<=curSize) {            if(saveOut)                *saveOut=data[idxDelete];            for(int i=idxDelete;i<curSize;i++)                data[i-1]=data[i];            curSize--;            return true;        }        return false;    }    void display(){        getInfo();        for(int i=0;i<curSize;i++){            printf("%d elem is %d\n",i,data[i]);        }    }    //查找数据 s 是否在表里面    //s 不在表里面,返回-1,否则返回 s 在表里的下标    int  find(T s){        for(int i=0;i<curSize;i++) {            if(data[i] == s){                return i;            }        }        return -1;    }    //打印顺序表的信息    void getInfo(){        printf("顺序表[0x%x] 容量:%d,当前大小:%d\n",data,capacity,curSize);    }    ///插入    bool insert(T elemInsert,int idxInsert=-1){        //数据元素已经满员但是扩容失败了        if(curSize>=capacity-1 && 0 != enlargeSize())            return false;        if(idxInsert>0){            for(int j=curSize-1;j>=idxInsert;j--){                data[j+1]=data[j];            }            idxInsert--;        }else{            idxInsert=curSize;        }        data[idxInsert]=elemInsert;        curSize++;        return true;    }    bool isFull(){        return curSize+1>=capacity;    }    bool isEmpty(){        return curSize==0;    }    bool isValidIndex(int idx) {        if(idx < 0 || idx > curSize){            return false;        }        return true;    }    int length(){        return curSize;    }private:    T*  data;    int curSize;    int capacity;    //扩容操作    //返回0 已经成功扩容了一倍    //返回-1,扩容失败    int enlargeSize(){        capacity <<= 1;        T* nb=(T*)calloc(capacity,sizeof(T));        if(nb){            memmove(nb,data,curSize*sizeof(T));            printf("[TIP]SeqList(0x%x)已满,自动扩展当前大小一倍\n",data);            data=nb;            return 0;        }        return -1;    }    ///初始化    int init(int nSize=SEQLIST_DEFAULT_SIZE){        data=(T*)calloc(nSize,sizeof(T));        if(!data){            return -1;        }        capacity=nSize;        curSize=0;        return 0;    }};#ifndef DYLIBint main(){    SeqList<int> isl;    int testArr[11]={40,41,42,43,44,140,142,143,144,145,146};    for(int i=0;i<sizeof(testArr)/sizeof(testArr[0]);i++) {        isl.insert(testArr[i]);    }    isl.display();    //insert again    for(i=0;i<sizeof(testArr)/sizeof(testArr[0]);i++) {        isl.insert(testArr[i]);    }    isl.display();    return 0;}#endif
0 0
原创粉丝点击