• 数据结构之线性结构之线性表


    一. 线性表及其实现

    如何表示多项式:f(x)=a0+a1x+...+an-1xn-1+anxn

    1. 多项式的项数n;
    2. 各项系数 ai 及指数 i

    顺序存储结构直接表述:一般数组

    顺序存储结构表示非零项:结构数组

    方法二中如果要对各项进行相加时,注意两项的指数需要按照降序或者升序排列

    链表结构存储非零项

     线性表:由同类型数据元素(可以是自定义的结构体等)构成有序序列的线性结构

     

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

    #define MAXSIZE 10
    typedef struct {
        int Data[MAXSIZE];
        int Last;
    }List;
    
    List L, *PtrL;
    //访问下标为i的元素:L.Data[i]或者PtrL->Data[i]
    //线性表的长度:L.Last+1或者PtrL->Last+1;由于数组从0开始,而Last表示数组的下标

     主要操作的实现

    初始化

    List *MakeEmpty()
    {
        List *PtrL = new List;//new的操作:申请存储空间并且初始化
        PtrL->Last = -1;
        return PtrL;
    }

    查找

    int Find(int X, List *PtrL)
    {
        int i = 0;
        while (i<=PtrL->Last&&PtrL->Data[i]!=X)//i<ptrl的长度,并没找到x时继续往下找
        {
            i++;
        }
        if (i>PtrL->Last)
        {
            return -1;
        }
        else
        {
            return i;
        }
    }

    插入:先移动再插入

    由于数组从0开始,第 i 个位置对应的下标数为 i-1

    void Insert(int X, int i, List *PtrL)//X为插入的数字,i为插入的位置
    {
        if (PtrL->Last == MAXSIZE - 1)//先检查表是否还有空间,如果表空间已满,不能再插入
        {
            printf("表满");
            return;
        }
        if(i<1||i>PtrL->Last+1)
        {
            printf("插入位置不合法");
            return;
        }
        for (int j = PtrL->Last; j >=i-1; j--)
        {
            PtrL->Data[j + 1] = PtrL->Data[j];//从数组最后一个数开始往后移一,直到移动到i-1位置位置,此时i-1的位置为空
        }
        PtrL->Data[i - 1] = X;// 插入新元素
        PtrL->Last++; //last指向的位置也要往后移动1
        return;
    }

    删除:后面元素依次往前移动

    void Delete( int i, List *PtrL)//i为删除的位置
    {
        if (i<1 || i>PtrL->Last + 1)
        {
            printf("插入位置不合法");
            return;
        }
        for (int j = i; j <=PtrL->Last; j++)
        {
            PtrL->Data[j - 1] = PtrL->Data[j];//从第i位置开始,后面依次往前移动一个位置
        }
        PtrL->Last--; //last指向的位置也要往后移动1
        return;
    }

    线性表的链式存储实现:逻辑上相邻,物理存储位置上不相邻

    插入删除不需要移动数据元素,只需要修改链

    typedef struct Node {
        int Data;
        struct Node *Next;
    } ListNode;
    
    ListNode LN, *PtrlN;

    主要操作

    求表长

    int Length(ListNode *PtrlN)
    {
        ListNode *p = PtrlN;//定义一个临时变量指向表的第一个结点
        int j = 0;
        while (p)
        {
            p = p->Next;
            j++;            //当前p指向第j个结点
        }
        return j;
    }

    查找

    按序号查找:FindKth;

    ListNode *FindKth(int K, ListNode *PtrlN)//K为需要找到的序号为K的,即第K个
    {
        ListNode *p = PtrlN;
        int i = 1;
        while (p!=NULL&&i<K)
        {
            p = p->Next;
            i++;
        }
        if (i == K) return p;
        else  return NULL;
    }

    按元素查找:FindKth;

    ListNode *Find(int X, ListNode *PtrlN)//X为需要查找的元素
    {
        ListNode *p = PtrlN;
        while (p!=NULL&&p->Data!=X)
        {
            p = p->Next;
        }
        return p;
    }
    //返回值为null,则说明没有找到

    插入

    先找到插入点之前的那个结点,即i-1的结点

    ListNode *Insert(int X, int i, ListNode *PtrlN)//X为插入的数字,i为插入的位置
    {
        ListNode *p;
        if (i==1)//新结点插入在表头
        {
            ListNode *s = new ListNode;
            s->Data = X;
            s->Next = PtrlN;
            return s;
        }
        p = FindKth(i - 1, PtrlN);
        if (p==NULL)
        {
            printf("参数i出错");
            return NULL;
        }
        else
        {
            ListNode *s = new ListNode;
            s->Data = X;
            s->Next = p->Next;
            p->Next = s;   //注意,此处和上面一个语序不能颠倒,否则s的next还是s
            return PtrlN;
        }
    }

    一段存储空间存放链表,ptrlN和p都只是指向其中的一个指针,指向哪个位置,就从该位置开始一直到链表的最后

     删除

     删除一定要记住释放删除点的内存

    ListNode *Delete(int i, ListNode *PtrlN)//X为插入的数字,i为插入的位置
    {
        ListNode *p;
        if (i == 1)//删除结点在表头
        {
            ListNode *s = PtrlN;
            if (PtrlN != NULL)PtrlN = PtrlN->Next;
            else return NULL;
            delete(s);   //一定记住要释放链表中删除点的内存
            return PtrlN;
        }
        p = FindKth(i - 1, PtrlN);
        if (p == NULL)
        {
            printf("参数i出错");
            return NULL;
        }
        else if (p->Next == NULL)
        {
            printf("参数i出错");
            return NULL;
        }
        else
        {
            ListNode *s = p->Next;
            p->Next = s->Next;
            delete(s);   //注意,此处和上面一个语序不能颠倒,否则s的next还是s
            return PtrlN;
        }
    }

    广义表:

    1. 线性表的推广;
    2. 广义表中元素可以是单元素也可以是另一个广义表
    3.  union

    多重链表:链表的节点可能同时隶属于多个链;结点的指针域会有多个;

     

     

  • 相关阅读:
    C++服务器开发之基于对象的编程风格
    C++服务器开发之笔记三
    InstallShield 脚本语言学习笔记
    Win.ini和注册表的读取写入
    MFC中如何画带实心箭头的直线
    UE4新手引导之下载和安装虚幻4游戏引擎
    SQLServer · BUG分析 · Agent 链接泄露分析(转载)
    mysql5.6版本开启数据库查询日志方法
    远程读取json数据并写入数据库
    js中的什么时候需要用new来实例化?
  • 原文地址:https://www.cnblogs.com/xiaoxue126/p/9033163.html
Copyright © 2020-2023  润新知