大话数据结构||学习笔记||从开头至链表||cc++

    技术2022-07-11  72

    一 day 4

    1 时间复杂度 1-1 线性阶 1-2 对数阶 1-3 平方阶 常见时间复杂度表 2 线性表 2-1 线性表顺序存储结构 线性表的长度与数组长度区分 线性表的顺序存储的结构代码

    #define MAXSIZE 20 //存储空间初始分配量 typedef int ElemType; // 暂定int typedef struct { ElemType date[MAXSIZE]; //数组存储数据成员,最大值为MAXSIZE int length; //线性表当前长度 }SqList;

    用数组存储,那么存储器中的每个存储单元都是有编号的,这个编号称为地址 那么,对于每个线性表位置的存入与取出,对于计算机来说都是相同的时间。它的存储时间性能为O(1)。我们通常把具有这一特点的存储结构称为顺序存储结构。 3 顺序存储结构的插入与删除 3-1 获得元素操作 // wr

    #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef int Status; /* Status 是函数类型,其值是函数结果状态代码,如OK 初始条件:顺序线性表L存在,1<=i<=ListLength(L) 操作结果:用e返回L中第i个数据元素的值*/ Status GetElem(SqList L, int i, ElemType *e)//这个函数为什么我调用不起来 { if (L.length == 0 || i<1 || i>L.length) return ERROR; *e = L.date[i - 1]; return OK; }

    3-2 插入操作 插入算法的思路

    若插入位置不合理,抛出异常若线性表长度>=数组长度,则抛出异常或动态增加容量从最后一个位置开始向前遍历,直到i,分别将它们向后移一位插入元素到i处表长+1 Status ListInsert(SqList *L, int i, ElemType e) { int k; if (L->length == MAXSIZE)//顺序线性表已满 return ERROR; if (i<1 || i>L->length + 1)//当i不在范围内 return ERROR; if (i <= L->length) { for (k = L->length; k >= i - 1; k--)//将要插入位置后数据元素向后移动一位 L->date[k + 1] = L->date[k]; } L->date[i - 1] = e; L->length++; return OK; }

    3-3 删除操作 删除算法的思路

    若删除位置不合理,抛出异常取出删除元素将删除位置后继元素前移表长-1 Status ListDelete(SqList *L, int i, ElemType *e) { int k; if (L->length == 0) //表长为0 return ERROR; if (i<1 || i>L->length ) // 删除位置不正确 { return ERROR; } *e = L->date[i - 1]; if (i < L->length)//若删除的不是最后一个元素 { for (k = i; k < L->length; k++)//删除位置后继元素前移 L->date[k - 1] = L->date[k]; } L->length--; return OK; }

    3-4 线性表的顺序存储结构的优缺点

    4 线性表的链式存储结构 头结点: 注意看头结点和第一个结点,头结点不是第一个结点 4-1 头结点和第一个结点的区别

    4-2 代码描述

    typedef struct Node { ElemType date; struct Node *next; }Node; typedef struct Node *LinkList;//定义 LinkList

    4-3 单链表的读取 算法思路: 代码实现:

    Status GetElem(LinkList L, int i, ElemType *e) { int j; LinkList p; //声明一结点p p = L->next;//让p指向链表L的第一个结点 j = 1; //j为计数器 while ( p && j<i)//p不为空,或计数器j还没有到i时,循环继续 { p = p->next; ++j; } if (!p || j > i) return ERROR;//第i个元素不存在 *e = p->date; //读取第i个元素 return OK; }

    4-4 单链表的插入与删除 插入:------------------------------------- 显然; 单链表第i个元素的插入操作算法思路 代码实现:

    Status ListInsert(LinkList *L, int i, ElemType e) { int j; LinkList p, s; p = *L; j = 1; while (p&&j < i) { p = p->next; ++j; } if (!p || j > i) return ERROR; //第i个元素不存在 s = (LinkList)malloc(sizeof(Node));//生成新结点(c标准函数)//加个头文件 s->date = e; s->next = p->next; //基操勿6 p->next = s; return OK; }

    删除:------------------------------------- 单链表第i个数据删除结点的算法思路 代码实现

    Status ListDelete(LinkList *L, int i, ElemType *e) { int j; LinkList p, q; p = *L; j = 1; while (p->next && j < i) { p = p->next; ++j; } if (!(p->next) || j > i) return ERROR; //第i个元素不存在 q = p->next; p->next = q->next; //将q的后继赋值给p的后继 *e = q->date; //将q结点中的数据给e free(q); //让系统回收此结点,释放内存 return OK; }

    4-5 单链表的整表创建 //wr 单链表整表创建的算法思路

    声明一结点p和计数器变量i

    初始化一空链表L

    让L的头结点的指针指向NULL,即建立一个带头结点的单链表

    循环

    生产一新结点赋值给p

    随机生成一数字赋值给p的数据域p->date

    将p插入头结点和与前一新结点之间 代码实现

    void CreateListHead(LinkList *L, int n)//头插法 { LinkList 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->date = rand() % 100 + 1; //随机生成100以内的数字 p->next = (*L)->next; (*L)->next = p; //插入到表头 } }

    上面为头插法,下面为尾插法

    void CreateListTail(LinkList *L, int n) { LinkList p, r; int i; srand(time(0)); *L = (LinkList)malloc(sizeof(Node));//为整个线性表?? r = *L; //r为指向尾部的结点 for (i = 0; i < n; i++) { p = (LinkList)malloc(sizeof(Node));//生成新结点 p->date = rand() % 100 + 1; //随机生成100以内的数字 r->next = p; //将表位终端结点的指针指向新结点 r = p; //将当前的新结点定义为表尾终端结点 } r->next = NULL; //表示当前链表结束 /// 解释见图 }

    解释: 4-6 单链表的整表删除 代码实现

    Status ClearList(LinkList *L) { LinkList p, q; p = (*L)->next; //p指向第一个结点 while (p) //没到表尾(NULL) { q = p->next; free(p); p = q; } (*L)->next = NULL; //头结点指针域为空 return OK; }

    简单总结 5 静态链表

    #define MAXSIZE 1000 typedef struct { ElemType date; int cur; //游标Cursor,为0时表示无指向 }Component,StaticLinkList[MAXSIZE];

    //space[0].cur为头指针,"0"表示空指针 Status InitList(StaticLinkList space) { int i; for (i = 0; i < MAXSIZE - 1; i++) space[i].cur = i+1; space[MAXSIZE - 1] = 0; //目前静态链表为空,最后一个元素的cur为0 return OK; }

    5-1 静态链表的插入

    int Malloc_SLL(StaticLinkList space) { int i = space[0].cur;//当前数组第一个元素存的值,就是返回的第一个备用空闲下标 if (space[0].cur) space[0].cur = space[i].cur;//由于要拿出一个分量来使用,所以我们就得 //把他的下一个分量用来做备用 return i; }

    差点没看懂。。。更有意思的在下面 插入:

    Status ListInsert(StaticLinkList L, int i, ElemType e) { int j, k, l; k = MAX_SIZE - 1; //注意k首先是最后一个元素下标 //???哪来的MAX_SIZE if (i < 1 || ListLength(L) + 1) return ERROR; j = Malloc_SLL(L);//获得空闲分量的下标 if (j) { L[j].date = e;//将数据赋值给此分量的date for (l = 1; l <= i - 1; l++)//找到第i个元素之前的位置 { k = L[k].cur; } L[j].cur = L[k].cur;//把第i个元素之前的cur赋值给新元素的cur L[k].cur = j; //把新元素的下标赋值给第i个元素之前的元素的cur return OK; } }

    解释: 5-2 静态链表的删除

    //删除在L中的第i个元素e Status ListDelete(StaticLinkList L, int i) { int j, k; if (i<1 || i>ListLength(L)) return ERROR; k = MAX_SIZE - 1; for (j = 1; j <= i - 1; j++) k = L[k].cur; j = L[k].cur; L[k].cur = L[j].cur; Free_SLL(L, j); return OK; }

    void Free_SLL(StaticLinkList space, int k) { space[k].cur = space[0].cur;//把第一个元素cur值赋给要删除的分量cur space[0].cur = k; //把要删除的分量下标赋值给第一个元素的cur }

    int ListLength(StaticLinkList L) { int j = 0; int i = L[MAX_SIZE - 1].cur; while (i) { i = L[i].cur; j++; } return j; }

    静态链表的优缺点: 6 循环链表 7 双向链表

    typedef struct DulNode { ElemType date; struct DulNode *prior; struct DulNode *next; } DulNode,*DuLinkList ;

    插入:

    s->prior = p; //把p赋值给s的前驱 1 s->next = p->next;//把p->next赋值给s的后继 2 p->next->prior=s; //把s赋值给p->next的前驱 3 p->next=s; //把s赋值给p的后继 4

    删除: 第三章到此结束。根本没搞明白有木有…下一章是栈与队列。 大话数据结构||学习笔记||从开头至链表||c/c++;

    Processed: 0.014, SQL: 9