数据结构线性结构

简介: 数据结构线性结构

数据结构---线性结构

线性表

“线性表”:是由同类型数据元素构成有序序列的线性结构

  • 表中元素个数称为线性表的长度
  • 线性表中没有元素的时候,称为空表
  • 表的起始位置称为空表,表的结束位置称为表尾

线性表的顺序存储实现

利用数组的连续存储空间顺序存放线性表的各元素

LAST存储线性表中最后一个元素的位置

线性表的长度为LAST+1

主要操作实现

  1. 初始化(建立空的顺序表)

    LIST MakeEmpty()
    {
        List Ptrl;
        Ptrl = (List)malloc(sizeof(struct LNode));
        Ptrl ->Last = -1 //-1代表无元素,0代表有一个元素
        return Ptrl;
    }
  2. 查找

    int Find (ELementType X,List Ptrl)
    {
        int i = 0;
        while (i<= Ptrl->Last && Ptrl->DAta[i]!=X)
            i++;
        if (i>Ptrl->Last) return -1;  //未找到
        else return i;  // 找到
    }
  3. 插入(第i个位置上插入一个X,实际上是数组中的i-1)

    要先把i-1空出来,所以先移动,在插入
    
    ```c

    void Insert (ElementType X,int i ,List Ptrl)
    {

       int j;
       if (Ptrl->Last == MAXSIZE-1){
           print("表满");
           return;
       }
       if (i<1||i>Ptrl->Last+2){
           pint("位置不合法");
           return;
       }
       for(j = Ptrl->Last;j>=i-1;j--)
           Ptrl->DAta[j+1] = Ptrl->Data[j];//村后往前移动
       Ptrl->Data[i-1] = X;
       Ptrl->Last++;//Last仍然指向最后一个元素
       return;

    }

    
    4. 删除(删除表中第i位置上的元素)
       i-1删除掉,并把后面的移动到前面
    
        void Delete(int i,List Ptrl){
            int j;
            if(i<1||i>Ptrl->Last+1){
                print("不存在这个位置");
                return;}
            for(j=i;j<=Ptrl->Last;j++)
                Ptrl->Data[j-1] = Ptrl->Data[j];//从i前往后移动
            Ptrl->Last--;
            return;
        } 
        ```
    

线性表的链式存储实现

主要操作的实现

  1. 求表长

    int Length(List Ptrl)//遍历链表来求表长
    {
        List p= Ptrl;
        int j = 0;
        while(p){
            p=p->Next;
            j++;
        }
        return j;
    }
  2. 查找

    (1) 按序号查找,找到第K个

    List FindKth(int K, List Ptrl)
    {List p= Ptrl;
    int i= 1;
    while(p!=NULL&&i<K){
        p=p->Next;
        i++;
    }
    if(i==K) return p;
    else return NULL;
    }

    (2) 按值查找

    List Find(ElementType X,List Ptrl){
        List p = Ptrl;
        while(p!NULL&&p->Data!=X)
            p=p->Next;
        return p;
    }
  3. 插入

    List Insert(ElementType X,int i ,List Ptrl)
    {
        List p,s;
        if(i == 1){  //如果是插在表头,那么返回的就不是原来的表头指针Ptrl了,而是s了。
            s = (List)malloc(sizeof(struct LNode));
            s->Data = X;
            s->Next = Ptrl;
            return s;
        }
        p = FindKth(i-1,Ptrl);//找到要插入的前一个的位置
        if(p == NULL){
            print("参数错误");
            return NULL;
        }else{
            s=(List)malloc(sizeof(struct LNode));
            s->Data = X;
            s-Next = p->Next;
            p->Next = s;
            return Ptrl;
        }
    }
  4. 删除(删除链表上第i个位置的结点)

    List Delete(int i, List Ptrl){
        List p,s;
        if(i==1){//讨论删除表头的情况
            s= Ptrl;
            if(Ptrl!=NULL) Ptrl = Ptrl->Next;
            else return NULL;//空表
            free(s);
            return Ptrl;
        }
        p= FindKth(i-1,Ptrl);//找到要删除的前一个的位置
        if(p==NULL){
            print("节点不存在"); return NULL;
        }else if(p->Next == NULL){
            print("节点不存在"); return NULL;
        }else{
            s=p->Next;
            p->Next=s->Next;
            free(s);//删除后一定要释放空间
            return Ptrl;
        }
    }

广义表

  • 广义表是线性表的推广
  • 对于线性表而言,n个元素都是基本的单元素
  • 广义表中,这些元素不仅可以是单元素也可以是另一个广义表

广义表的定义:

typedef struct GNode *GList;
struct GNode{
    int Tag;//标志域,0表示节点是单元素,1表示节点是广义表
    union{//字表的指针域与单元素数据域Data复用,即共享存储空间
        ElementType Data;
        GList SubList;
    }URrgion;
    GList Next;//指向后继节点
};

多重链表

多重链表:链表中的节点可能同时隶属多个链

  • 多重链表中的节点的指针域会有多个,如上述所说包含NEXT和SubList 两个指针域
  • 但包含两个指针域的链表不一定是多重链表,比如双向链表就不是多重链表

多重链表应用

十字链表存储稀疏矩阵(4行5列7项的稀疏矩阵)

wangxining_2021-05-18_15-26-04

结点的结构:

wangxining_2021-05-18_15-28-15

堆栈

堆栈:具有一定操作约束的线性表

  • 只在一端插入,删除

后入先出是其最大的特点

### 栈的顺序存储实现

栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成

  1. 入栈

    void Push (Stack PtrS, ElementType item)
    {
        if (PtrS->Top == MaxSize-1){
            print("堆栈满"); return;
        }else {
            PtrS->Data[++(PtrS->Top)] = item;//item赋值给Top上面的那个位置
            return;
        }
    }
  2. 出栈

    ElementTpe Pop(Stack PtrS)
    {
        if (Ptrs->Top == -1){
            print("堆栈空");
            return ERROR;
        }else
            return (PtrS->Data[(PtrS->Top)--]);//既能将Top传出去,还能实现Top减一
    }

栈的链式存储实现

栈的链式存储结构实际上是一个单链表,叫做链栈。插入和删除操作只能在栈顶操作。所以Top只能指向链头,指向链尾的时候你删了以后你找不到前一个结点了,你就没办法给Top赋值了。

  1. 判断堆栈为空:

    S->Next == NULL

  2. S是指针,指向堆栈的头结点 ,头结点是 不存储数据的,头结点所指向的下一个结点才存储元素。

    所以你要注意一点,堆栈上面的用数组实现,top所指的是有元素的;而链表实现的top指的是空的,是没有元素的。
  3. 入栈

    void Push (ElementType item, Stack S)
    {
        struct SNode *TmpCell;
        TmpCell=(struct SNode*)malloc(sizeof(struct SNode));
        TmpCell->Element = item;
        TmpCell->Next = S->Next;
        S->Next = TmpCell;
    }
  4. 出栈

    ElementType Pop(Stack S)
    {
        struct SNode *FirstCell;
        ElementType TopElem;
        if(IsEmpty(s)){
            printf("堆栈空"); return NULL;
        }else{
            FirstCell = S->Next;
            S->Next = FirstCell->Next;
            TopElem = FirstCell->Element;
            free(FirstCell);
            return TopElem;
        }
    }

堆栈应用:后缀表达式求值

中缀表达式变为后缀表达式的流程:

从头到尾读取中缀表达式的每个对象,对不同对象按照不同情况处理。

  1. 运算数:直接输出;
  2. 左括号:压入堆栈;
  3. 有括号:将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出);
  4. 运算符:

    • 若遇到优先级大于栈顶运算符时,把它压栈;
    • 若遇到优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出;再比较新的栈顶运算符,直到该运算符遇到大于栈顶运算符优先级或者左括号为止,然后将该运算符压栈;
  5. 若各对象处理完毕,则把堆栈中存留的运算符一并输出。

队列

队列:具有一定操作约束的线性表。

  • 先进先出是其最大的特点

队列的顺序存储实现

队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量front以及一个记录队列尾元素位置的变量rear组成。

队列结构:

#define Maxsize
struct QNode{
    ELementType Data[MaxSize];
    int rear;
    int front;
};
  • front 和 rear等于负1的时候队列为空
  • front实际上指向的是头元素的前一个位置,而rear指向的是尾元素

循环队列:就好比把数组首尾相连一样:

  • 此时front = rear就代表了队列空
  • 为了防止无法区别队列空和队列满所以我们可以:1. 使用额外标记,标记目前使用几个位置。2. 仅使用n-1个数组空间。
  • rear+1 = front代表 队列满
  1. 入队列:(这里采用仅使用n-1个位置的方法)

    void AssQ(Queue PtrQ,ElementType item)
    {
        if((PtrQ->rear+1)%MaxSize == PtrQ->front){
            print("队列满");
            return;
        }
        PtrQ->rear = (PtrQ->rear+1)%MaxSize;
        PtrQ->Data[PtrQ->rear] = item;
    }
  2. 出队列:

    ElementType DeleteQ(Queue PtrQ)
    {
        if(PtrQ->front == PtrQ->rear){
            print("队列空");
            return ERROR;
        }else{
            PtrQ->front = (PtrQ->front+1)%MaxSize;
            return PtrQ->Data[PtrQ->front];
        }
    }

队列的链式存储实现

队列的链式存储结构也可以用一个单链表实现。插入和删除操作分别在链表的两头进行。

front作删除操作,rear做插入操作。所以链表头做front。链表尾做rear。

  • front=NULL 队列空

队列结构:

struct Node{
    ElementType Data;
    struct Node *Next;
};
struct QNode{
    struct Node *rear;//指向队尾
    struct Node *front;//指向队头
};

wangxining_2021-05-20_23-05-18

  1. 出队:

     ElementType DeleteQ(Queue PtrQ)
     {
         struct Node *FrontCell;
         ElementType FrontElem;
         
         if(PtrQ->front == NULL){
             printf("队列空");
             return ERROr;
         }
         FrontCell = PtrQ->front;
         if(PtrQ->front == PtrQ->rear)//若队列元素只有一个元素
             PtrQ->front = PtrQ->rear = NULL;//删除队列后置空
         else
             PtrQ->front = PtrQ->front->Next;
         FrontElem = FrontCell->Data;
         free(FrontCell);//释放被删除的空间
         return FrontElem;
     }
目录
相关文章
|
13天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
56 16
|
2月前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
5月前
|
存储 算法
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
38 0
|
5月前
|
存储 算法 Linux
【数据结构和算法】---二叉树(1)--树概念及结构
【数据结构和算法】---二叉树(1)--树概念及结构
50 0
|
5月前
|
存储 算法
【数据结构和算法】--队列的特殊结构-循环队列
【数据结构和算法】--队列的特殊结构-循环队列
32 0
|
1月前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
|
2月前
|
机器学习/深度学习 算法 Java
[算法与数据结构] 谈谈线性查找法~
该文章详细介绍了线性查找法的基本概念与实现方法,通过Java代码示例解释了如何在一个数组中查找特定元素,并分析了该算法的时间复杂度。
|
1月前
探索顺序结构:栈的实现方式
探索顺序结构:栈的实现方式
|
1月前
|
存储 算法
【数据结构】二叉树——顺序结构——堆及其实现
【数据结构】二叉树——顺序结构——堆及其实现
|
2月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。