大话数据结构笔记

/*
 第一章  数据结构绪论

 数据结构是一种或多种特定关系的数据元素的集合

 实时排队系统:队列结构

 数据:是描述客观事务的符号,是计算机可以操作的对象.

  数据项: 一个数据元素可以由若干个数据项组成.不可分割的最小单位.
  结构: 简单理解就是关系.逻辑结构,物理结构.

  逻辑结构:  集合  线性结构 树形结构  图形结构
  物理结构: 逻辑结构在计算机中的存储形式.  顺序结构 链式结构
  (存储单元不连续)

  逻辑结构是面向问题的,而物理结构是面向计算机的.其基本的目标是将数据及其逻辑关系存储在计算机的内存中.

  ADT  抽象数据类型名
  Data
    数据元素之间的逻辑关系的定义
  operation
    操作1
        初始化
        操作结果描述
    操作2
        ...
    操作n
        ...

  endADT


  第二章  算法

  解决特定问题的步骤描述 在计算机中表现为指令的有限序列,并且每条指令标识一个或多个操作  特性: 输入输出 有穷性 确定性 和可行性
  时间效率高 和存储量低

  算法效率的度量方法:
事后统计法,利用计算机计时器对不同算法编制的程序的运行时间进行比较
事前分析估算法:  依据统计方法对算法进行估算
    int i, sum = 0, n=100;   执行1次
    for(i = 1; i <= n; i++)  执行n+1次
    {
        sum = sum + i;   执行1次
    }
    printf("%d",sum);   执行1次


    int sum =0, n=100;   执行1次
    sum = (1 + n)*n/2;   执行1次
    printf("%d\n",sum);  执行1次

    操作数量是f(n)=n;

     算法的事件复杂度:语句执行的总次数T(n) 是关于问题规模的函数
     进而分析T(n)随n的变化情况并确定T(n)的数量.算法的事件度量
     T(n)=O(f(n)).f(n)是问题规模n的某个函数.

     常熟阶:
     顺序结构事件复杂度:O(1);执行次数恒定,不会随着n的变大而变化

     线性阶:
     循环的时间复杂度为O(n)因为循环体中的代码必须执行n次

     对数阶:
     O(logn):

     平方阶:
    嵌套循环的时间复杂度,O(n^2);


    算法的时间复杂度看得不是太懂.



第三章  线性表

    线性表(List):零个或对个数据元素的有序集合
    线性表的抽象数据类型:
    ADT  线性表(Lsit)
    DATA
        数据对象集合{a1,a2,a3,a4,a5....an},每个元素的类型均为
        DataType,数据元素之间的关系时一一对应.
    operation:
        InitList(*L)
        ListEmpty(L)
        clearList(*L)
        GetList(L,i,*e)
        LocateElem(L,e)
        ListInsert(*L,i,e)
        ListDelete(*L,i,*e)
        List Length(L)

    A=A并B
    void union(List *La,List* Lb)
    {

        int La_len,Lb_len,i;
        ElemType e;
        La_len = ListLength(La);
        Lb_len = ListLength(Lb);

        for(i=1;i<=Lb_len;i++)
        {
            GetElem(Lb,i,e);
            if(!Locate(La,e,equal))
            ListInsert(La,++La_len,e);
        }
    }


    线性变的顺序存储结构:把一定内存给占了,然后相同数据元素依次放入
    线性表的顺序存储结构:
    #defienf MAXSIZE 20
    typedef int ElemType;
    typedef struct
    {
        ElemType data[MAXSIZE];
        int length;
    }Sqlist;

    三个属性:
        1 存储空间的起始位置: 数组data;
        2 线性表的最大存储容量: 数组长度 Maxsize
        (存储线性表的存储空间的长度)
        3 线性表的当前长度:length
        (数据元素的个数)

    每个元素占c个存储单元,那么线性表中第i+1个数据元素的存储位置和第i个元素的存储位置的关系.
    LOC(a(i+1)) = LOC(a(i))+c
    LOC(a(i)) = LOC(a(1))+(i-1)*c

    顺序存储结构的插入与删除

    1 获得元素
        #define OK 1
        #define ERROR 0
        #define TRUE 1
        #define FALSE 0
        typedef int Status;
        Status 是函数类型,其值为函数结果状态代码
        e返回L中i位置元素的值
        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;
        }

        插入算法的思路:
        1 如果插入位置不合理,抛出异常
        2 如果线性表的长度等于数组长度,则抛出异常和动态增加容量;
        3 从总后一个元素向前遍历到第i个位置,分别将他们都向后移动一个位置
        4 将要插入的元素填入位置i处

        Status ListInsert(SqList *L,int i,ElemType e)
        {
            int k;
            if(L->length == MAXSIZE)
                return ERROR;
            if(i<1||i>L-length+1)
                return ERROR;
            if(i<=L->length)  //中间插入
            {
                 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;

        }

        删除算法思路:
        1 如果位置不合理 抛出异常
        2 取出元素
        3从删除元素开始遍历到最后一个元素,分别将他们都想前移动一个位置
        4 表长减1

        Status ListDelete(Sqlit *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;
        }

        时间复杂度:
        1 最后一个元素 O(1)
        2 最坏情况O(n)

        优点: 无需为表示元素的逻辑关系而增加额外的空间  可以快速存储表中的人以位置元素
        缺点: 难以确保存储空间的容量  插入删除需要移动大量元素,造成存储空间"碎片"
      线性表的链式存储: 数据域和指针域
      头指针指向链表的第一个节点的指针.无论链表是否为空,头指针均不为空.
      头节点放在头一个元素之前.
      单链表的存储结构:
      typedef struct Node
      {
            ElemType data;
            struct Node* next;

      }Node;
      typedef struct Node* Linklist;



      获得链表的第i个数据的算法:
      1 声明一个p指针指向链表的第一个节点 初始化j从1开始
      2 当j<i时遍历链表,让p的指针向后移动 不断指向下一个节点,j累加
      3 若p为空,则元素不存在
      4 查找成功 返回节点p

      Status GetElem(LinkList L,int i, elemtype *e)
      {
            int j=0;
            Linklist p;
            p = L->next;//带有头节点的链表
            j=1;
            while(p&&j<i)
            {
                p = p->next;
                ++j;
            }
            if(!p || j>i)
                return ERROR;
            *e = p->data;
            * reutrn OK;
        }

        链表的插入:
        代码实现
        Status ListInsert(Linklist *L,int i;ElemType)
        {
            int j;
            Linklist p,s;
            p = *L;
            j= 1;
            while(p&&j<i)  //查找第i个节点
            {
                p=p->next;
                j++;
            }
            if (!p|| j>i)
                reutrn ERROR;
            s = (Linklist)malloc(sizeof(Node));
            assert(s);
            s->data = e;
            s->next = p->next;
            p->next = s;
            return OK;
         }

         链表的删除:(这里参数1 ,3 是结构参数,传的是指针)
         Status Listdelete(Linklist *L,int i,ElemType *e)
         {
              int j=1;
              Linklist p,q;
              p=*L;
              while(p->next&&j<i)
              {
                    p=p->next;
                    j++;
                }
                if(!(p->next)||j>i)
                    return ERROR;
                 q=p->next;      //保存要删除的节点
                 p->net = q->next;
                 *e = q->data;
                 free(q);
                 q=NULL;
                 return OK;

         }
         时间复杂度: 插入删除都是O(1);查找O(n);
         man{  Linklist L=NULL; CreateList(&L);}
         创建链表:  (参数1 是一个二阶指针)
         void CreateListHead(Linklsit *L,int n)
         {
            ListList 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;
            }

            linklist r=*L;
            for(i=0;i<n;i++)
            {
                p=(Linklist)malloc(sizeof(Node));
                p->data = rand()%100+1;  //
                r->next = p;
                r =p;

            }
            r->next =NULL;
         }
         Status ClearList(Linklist *L)
         {
                Linklist p,q;
                p=(*L)->next;
                while(p)
                {
                    q=p->next;
                    free(p)
                    p=q;
                }

                (*L)->next = NULL;
                retrun OK;
            }

            顺序结构用一段连续的存储单元  单链表采用任意存储单元
            顺序结构需要预分配空间       单链表需要时分配
            查找  顺序结构O(1)    单链表  O(n)
            插入删除  顺序结构O(n)  单链表O(1)

静态链表
    用数组描述的链表叫做静态链表
    #define MAXSIZE 1000
    typedef struct
    {
        Elemtype data;
        int cur;   //游标,为0 时无指向
     }Component,StaticLinkList[MAXSIZE];

     Status InitList(StaticLinkList space)
     {
        int i=0;
        for(i=0;i<MAXSIZE; i++)
            space[i].cur = i+1;  //初始化游标
        space[MAXSIZE].cur = 0; 最后一个元素的cur为0
        return OK;

        }

        int Malloc_SLL(StaticLinkList space)
        {
            int i=space[0].cur;   1 //当前数组第一个元素的cur
            if(space[0].cur)
                space[0].cur = space[i].cur;
             return i;

        }
        status ListInsert(StatusLinkList L,int i,ElemType e)
        {
            int j,k,l;
            k = MAX_SIZE-1;
            if(i<1||i>ListLength(L)+1)
                retrun ERROR;
            j = Malloc_SSL(L);
            if(j)
            {
                L[j].data = e;
                for(l=1;l<=i-1;l++)
                    k = L[k].cur;
                L[j].cur = L[k].cur;
                L[k].cur = j;
                reuturn OK;

            }
            return ERROR;
        }

        静态链表看不懂
        ......

        循环链表:
        头节点:  尾节点rearA->next;
        合并链表:   保存头节点 p=rear->next;
                            rearA->next = rearB->next->next;
                            rearB->next = p;
                            free(p);               //感觉这里有问题 应该释放rearB的头节点

         双向链表:
         typedef struct DulNode
         {
            ElemType data;
            struct DulNode *prior;
            struct DulNode *next;

            }DulNode,*DulNodeList;

            p->next->prior = p =p->prior->next;

            插入位置p后面 节点s ;
            s->prior = p;
            s->next=p->next;
            p->next->prior = s;
            p->next = s;

            删除
            p->prior->next = p->next;
            p->next->prior = p->prior;




 */

posted @ 2019-05-25 19:09  countryboy666  阅读(542)  评论(0编辑  收藏  举报