📔
数据结构简单学
  • 序言
  • 绪论
    • 数据结构基本概念
    • 算法基本概念
  • 线性表
    • 顺序表
    • 单链表
    • 双链表
    • 循环链表
    • 区别
  • 栈和队列
    • 栈
    • 队列
    • 应用
  • 数组
  • 字符串
  • 哈希表
  • 树和二叉树
    • 基本概念
    • 二叉树遍历与构造
    • 线索二叉树
    • 树、森林
    • 二叉排序树
    • 平衡二叉树
    • 哈夫曼树
  • 图
    • 基本概念
    • 图的存储及基本操作
    • 图的遍历
    • 图的应用
  • 查找算法
  • 排序算法
    • 冒泡排序
    • 简单选择排序
    • 简单插入排序
    • 希尔排序
    • 归并排序
    • 快速排序
    • 堆排序
  • STL系列
    • 基础知识
    • Vector 动态数组
    • List 链表
    • Stack 栈
    • Queue 队列
    • Set 集合
    • Map
  • 总结与展望
Powered by GitBook
On this page
  • 定义
  • 静态定义:
  • 动态分配
  • 顺序表上的基本操作:
  • 初始化
  • 求表长
  • 按值查找
  • 按位查找
  • 插入操作
  • 删除操作
  • 动态分配的那点事
  • 初始化顺序表
  • 增加动态数组的长度

Was this helpful?

  1. 线性表

顺序表

  线性表的顺序存储又称顺序表。表中元素的逻辑顺序与其物理顺序相同。

定义

静态定义:

#define MAXSIZE 50;                    //定义线性表的最大长度
typedef struct {
    ElemType data[MAXSIZE];            //顺序表的元素
    int length;                        //顺序表的当前长度
}Sqlist;                            //顺序表的类型定义

  静态分配时,数据量小的话,会造成数组空间的浪费;而如果是数据量大的话,就会造成溢出,进而导致程序崩溃。所以我们采用下面更灵活的方式来

动态分配

#define InitSize 100                //定义线性表的初始长度
typedef struct {                    
    ElemType* data;                    //指示动态分配数组的指针
    int MAXSIZE,length;                //数组的最大容量和当前个数
}Sqlist;

  C的初始化分配语句为:

L.data = (ElemType*)malloc(sizeof(ElemType)*InitSize);

  这句话的意思是malloc向系统申请分配 ( sizeof(ElemType)*InitSize )的内存空间,ElemType类型的指针指向这块内存的首地址。

  C++的初始化分配语句为:

L.data = new ElemType[InitSize];

顺序表上的基本操作:

初始化

//初始化顺序表(静态分配)
bool InitSqList(Sqlist &L) {
    for (int i = 0; i < MAXSIZE; i++) {
        L.data[i] = 0;
    }
    if (!L.data)
        exit(OVERFLOW);
    L.length = 0;
    return true;
}

求表长

int Length(Sqlist L) {
    return L.length;
}

按值查找

int LocateElem(Sqlist L,ElemType e) {
    for( int i = 0; i < L.length; i++){
        if( e == L[i]){
            return i + 1;
        }
    }
    return -1;
}

  最好情况:查找的元素就在表头,时间复杂度为O(1)

  最坏情况:查找的元素在表尾,时间复杂度为O(n)

  平均情况:比较的平均次数为 (n+1) / 2

  因此,线性表的按值查找操作算法时间复杂度为O(n)。

按位查找

ElemType GetElem(Sqlist L,int i) {
    return L[i-1];
}

插入操作

bool ListInsert(Sqlist &L,int i,ElemType e) {
    if( i < 1 || i > L.length + 1){                //判断输入的i是否符合范围
        return false;
    }
    if( L.length > MAXSIZE){                    //如果存储空间已满,则插入失败
        return false;
    }
    for( int i = L.length; i >= i; i--){        //将第i个元素及之后的元素后移
        L.data[i] = L.data[i-1];
    }
    L.data[i] = e;
    L.length ++;
    return true;    
}

  最好情况:在表尾插入,时间复杂度为O(1)

  最坏情况:在表头插入,时间复杂度为O(n)

  平均情况:所需移动结点的平均次数为 n/2

  因此,线性表的插入操作算法时间复杂度为O(n)。

删除操作

bool ListDelete(Sqlist &L,int i,ElemTyep &e) {         //删除第i位上的数,并通过e返回其值
    if( i < 1 || i > L.length){
        return false;
    }
    e = L.data[i];
    for( int i = i; i < L.length; i++){
        L.data[i-1] = L.data[i];
    }
    L.length --;
    return true;    
}

  最好情况:在表尾删除,时间复杂度为O(1)

  最坏情况:在表头删除,时间复杂度为O(n)

  平均情况:所需移动结点的平均次数为 (n-1) / 2

  因此,线性表的删除操作算法时间复杂度为O(n)。

动态分配的那点事

初始化顺序表

//初始化顺序表
void InitSeqList(SqList &L) {
    L.data = (ElemType*)malloc(sizeof(ElemType) * InitSize);
    //L.data = new ElemType[InitSize];   //C++动态分配
    L.length = 0;
    L.MaxSize = InitSize;
}

增加动态数组的长度

//增加动态数组的长度
void IncreaseSize(SqList &L, int len) {
    ElemType* p = L.data;                      //新建指针p指向数组首部,也就是p指针和data指针同时指向数组首位元素
    L.data = (ElemType*)malloc(sizeof(ElemType) * (L.MAXSIZE + len));  //在别处开辟(MAXSIZE+len)*sizeof(ElemType)连续的空间,  并将data指针指向这片空间的首地址
    for (int i = 0; i < L.length; i++) {
        L.data[i] = p[i];                    //将数据复制到区域
    }
    L.MAXSIZE += len;
    free(p);
}
Previous线性表Next单链表

Last updated 4 years ago

Was this helpful?