1.线性表的顺序表示



事件复杂度是要忽略高阶项系数和低阶项,上面的答案是O(n)



动态分配的数组仍属于顺序存储结构
什么是动态分配?
- int p=(int )malloc(sizeof(int)*10);申请了一个空间,用数组的方式去做。

所有数据结构的4种操作:
- 增删改查
什么是单步调试?
- 每执行一步,数据的变化是怎么样的,是否符合自己的预期。
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>typedef int ELemType;typedef struct LNode{ELemType data;struct LNode* next;//指向下一个结点}LNode,*LinkList;//头插法//和表尾无关,只动表头,所以变化L,初始化时表头就是表尾//先给表头申请空间,在判断插入的数据是否符合条件,符合则申请下一个链表空间//先让s指向L指向的元素(初始时为Null),(因为L不能同时指向两个结点,所以不先连接L和s),再让L指向s// 如果先让L指向s的话,那就以前的p的next就失效了//输入数据,执行循环void CreateList1(LinkList &L) {LNode* s;int x;L = (LinkList)malloc(sizeof(LNode));//带头结点的链表L->next = NULL;//L->data里面没有放东西scanf("%d", &x);//从标准输入读取数据//3 4 5 6 7 9999while (x != 9999) {//如果输出的不是9999,,则添加元素申请一个新空间给s,强制类型转换s = (LNode*)malloc(sizeof(LNode));s->data = x;//吧读取到的值给新空间中的data成员s->next = L->next;//让新结点的next指针指向链表的第一个元素(第一个放我们数据的元素)L->next = s;//让s作为第一个元素//第一个元素不是头结点,因为头结点什么也没存scanf("%d", &x);//从标准输入读取数据}}//尾插法// 不管表头的事,初始化时表头就是表尾,前面不动,只动表尾//先给表头申请空间,在判断插入的数据是否符合条件,符合则申请下一个链表空间//因为r是表尾,所以next为NULL//定义一个结构体s存要插入的数据,复制表头的地址,做表尾,用于确定尾部的位置(确定是否超出范围等等)//进入循环后,给s赋值和下一个结点地址,r的next由Null指向s,s成为表尾LinkList CreateList2(LinkList &L) {int x;L = (LNode*)malloc(sizeof(LNode));//申请一个带头结点的链表LNode* s, * r = L;//结构体指针,也可以写成LinkList s,r=L;r代表表尾结点,r指向表位尾部//创建r是为了让r始终指向尾部,否则下次插入就要从开头遍历到尾部scanf("%d",&x);while (x != 9999) {s = (LinkList)malloc(sizeof(LNode));s->data = x;r->next = s;//让尾部结点指向新结点r = s;//r指向是表尾结点scanf("%d",&x);}r->next = NULL;//让尾指针的next指针赋值为NULLreturn L;}//打印链表//不改变值,不用加引用,如果加引用的话最后的结果为Null//如果不想改变值且加了引用,可以把形参给另一个变量来操作另一个变量//如void PrintList(LinkList &a) LinkList L=a;void PrintList(LinkList L) {//要不要加引用,就是看是不是在子函数中要去改变主函数对应的变量,要改就要加。L = L->next;while (L != NULL) {//NULL是代表一张空的藏宝图,next是宝藏printf("%3d\n",L->data);//打印当前结点数据L = L->next;//指向下一个结点}}//按序列查找//先定义一个序号,代表链表当前位置,在定义链表p表示当前所在链表//判断序列是否合法// 进入循环遍历,判断链表是否为空,且当前位置不能大于要查的序列// 挨个遍历LinkList GetElem(LNode* L, int i) {int j = 1;//从第一个有数据的结点开始,因为下一步是L->next,所以j=1LinkList p = L->next;//让p指向下一个结点if (0 == i)return L;//i是0就返回头结点if (i < 1)return NULL;while (p&&j<i) {p = p->next;//让p指向下一个结点j++;}return p;}//按值查找LinkList LocateElem(LinkList L,ELemType e) {LinkList p = L->next;while (p != NULL&&p->data!=e) {p = p->next;}return p;}//往第i个位置插入元素bool ListFrontInsert(LinkList L,int i,ELemType e) {LinkList p = GetElem(L,i-1);//拿到要插入位置的前一个结点的地址值if (NULL == p)return false;LinkList s = (LinkList)malloc(sizeof(LNode));//给新结点申请空间s->data = e;s->next = p->next;p->next = s;return true;}//删除第i个位置的元素// 要找到前一个结点//需要两个链表,一个是结点前的,一个是结点后的,因为删除后要连接起来//判断前一个结点是否为空结点// 让前一个结点的next指向要删除结点的next// 释放当前要删除的结点,避免空指针异常//没有用引用,是因为没有改变L的值bool ListDelete(LinkList L,int i){LinkList p = GetElem(L, i - 1 );if (NULL == p) //判断p,因为要访问p->next如果为Null下面的程序就会崩溃return false;LinkList q = p->next;if (q == NULL)return false;p->next = q-> next;free(q);q = NULL;//为了避免野指针return true;}int main() {LinkList L;//链表头,是结构体指针类型LinkList search;CreateList2(L);//输入数据可以为3 4 5 6 7 9999(输入9999代表循环结束)PrintList(L);search=GetElem(L, 2);//查找链表第二个位置的元素值if (search != NULL) {printf("按序号查找成功\n");printf("%d\n",search->data);}search = LocateElem(L,6);//按值查询if (search != NULL) {printf("按值查找成功:%d\n", search->data);}ListFrontInsert(L,2,99);PrintList(L);//ListDelete(L, 4);//PrintList(L);return 0;}

