线性表
线性表的顺序结构,链式结构的实现。
image.png
image.png

1.线性表的顺序表示

image.png
image.png
image.png
事件复杂度是要忽略高阶项系数和低阶项,上面的答案是O(n)
image.png
image.png
image.png
image.png
动态分配的数组仍属于顺序存储结构
什么是动态分配?

  • int p=(int )malloc(sizeof(int)*10);申请了一个空间,用数组的方式去做。

image.png
所有数据结构的4种操作:

  • 增删改查

什么是单步调试?

  • 每执行一步,数据的变化是怎么样的,是否符合自己的预期。
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. typedef int ELemType;
  5. typedef struct LNode{
  6. ELemType data;
  7. struct LNode* next;//指向下一个结点
  8. }LNode,*LinkList;
  9. //头插法
  10. //和表尾无关,只动表头,所以变化L,初始化时表头就是表尾
  11. //先给表头申请空间,在判断插入的数据是否符合条件,符合则申请下一个链表空间
  12. //先让s指向L指向的元素(初始时为Null),(因为L不能同时指向两个结点,所以不先连接L和s),再让L指向s
  13. // 如果先让L指向s的话,那就以前的p的next就失效了
  14. //输入数据,执行循环
  15. void CreateList1(LinkList &L) {
  16. LNode* s;
  17. int x;
  18. L = (LinkList)malloc(sizeof(LNode));//带头结点的链表
  19. L->next = NULL;//L->data里面没有放东西
  20. scanf("%d", &x);//从标准输入读取数据
  21. //3 4 5 6 7 9999
  22. while (x != 9999) {
  23. //如果输出的不是9999,,则添加元素申请一个新空间给s,强制类型转换
  24. s = (LNode*)malloc(sizeof(LNode));
  25. s->data = x;//吧读取到的值给新空间中的data成员
  26. s->next = L->next;//让新结点的next指针指向链表的第一个元素(第一个放我们数据的元素)
  27. L->next = s;//让s作为第一个元素
  28. //第一个元素不是头结点,因为头结点什么也没存
  29. scanf("%d", &x);//从标准输入读取数据
  30. }
  31. }
  32. //尾插法
  33. // 不管表头的事,初始化时表头就是表尾,前面不动,只动表尾
  34. //先给表头申请空间,在判断插入的数据是否符合条件,符合则申请下一个链表空间
  35. //因为r是表尾,所以next为NULL
  36. //定义一个结构体s存要插入的数据,复制表头的地址,做表尾,用于确定尾部的位置(确定是否超出范围等等)
  37. //进入循环后,给s赋值和下一个结点地址,r的next由Null指向s,s成为表尾
  38. LinkList CreateList2(LinkList &L) {
  39. int x;
  40. L = (LNode*)malloc(sizeof(LNode));//申请一个带头结点的链表
  41. LNode* s, * r = L;//结构体指针,也可以写成LinkList s,r=L;r代表表尾结点,r指向表位尾部
  42. //创建r是为了让r始终指向尾部,否则下次插入就要从开头遍历到尾部
  43. scanf("%d",&x);
  44. while (x != 9999) {
  45. s = (LinkList)malloc(sizeof(LNode));
  46. s->data = x;
  47. r->next = s;//让尾部结点指向新结点
  48. r = s;//r指向是表尾结点
  49. scanf("%d",&x);
  50. }
  51. r->next = NULL;//让尾指针的next指针赋值为NULL
  52. return L;
  53. }
  54. //打印链表
  55. //不改变值,不用加引用,如果加引用的话最后的结果为Null
  56. //如果不想改变值且加了引用,可以把形参给另一个变量来操作另一个变量
  57. //如void PrintList(LinkList &a) LinkList L=a;
  58. void PrintList(LinkList L) {
  59. //要不要加引用,就是看是不是在子函数中要去改变主函数对应的变量,要改就要加。
  60. L = L->next;
  61. while (L != NULL) {//NULL是代表一张空的藏宝图,next是宝藏
  62. printf("%3d\n",L->data);//打印当前结点数据
  63. L = L->next;//指向下一个结点
  64. }
  65. }
  66. //按序列查找
  67. //先定义一个序号,代表链表当前位置,在定义链表p表示当前所在链表
  68. //判断序列是否合法
  69. // 进入循环遍历,判断链表是否为空,且当前位置不能大于要查的序列
  70. // 挨个遍历
  71. LinkList GetElem(LNode* L, int i) {
  72. int j = 1;//从第一个有数据的结点开始,因为下一步是L->next,所以j=1
  73. LinkList p = L->next;//让p指向下一个结点
  74. if (0 == i)
  75. return L;//i是0就返回头结点
  76. if (i < 1)
  77. return NULL;
  78. while (p&&j<i) {
  79. p = p->next;//让p指向下一个结点
  80. j++;
  81. }
  82. return p;
  83. }
  84. //按值查找
  85. LinkList LocateElem(LinkList L,ELemType e) {
  86. LinkList p = L->next;
  87. while (p != NULL&&p->data!=e) {
  88. p = p->next;
  89. }
  90. return p;
  91. }
  92. //往第i个位置插入元素
  93. bool ListFrontInsert(LinkList L,int i,ELemType e) {
  94. LinkList p = GetElem(L,i-1);//拿到要插入位置的前一个结点的地址值
  95. if (NULL == p)
  96. return false;
  97. LinkList s = (LinkList)malloc(sizeof(LNode));//给新结点申请空间
  98. s->data = e;
  99. s->next = p->next;
  100. p->next = s;
  101. return true;
  102. }
  103. //删除第i个位置的元素
  104. // 要找到前一个结点
  105. //需要两个链表,一个是结点前的,一个是结点后的,因为删除后要连接起来
  106. //判断前一个结点是否为空结点
  107. // 让前一个结点的next指向要删除结点的next
  108. // 释放当前要删除的结点,避免空指针异常
  109. //没有用引用,是因为没有改变L的值
  110. bool ListDelete(LinkList L,int i){
  111. LinkList p = GetElem(L, i - 1 );
  112. if (NULL == p) //判断p,因为要访问p->next如果为Null下面的程序就会崩溃
  113. return false;
  114. LinkList q = p->next;
  115. if (q == NULL)
  116. return false;
  117. p->next = q-> next;
  118. free(q);
  119. q = NULL;//为了避免野指针
  120. return true;
  121. }
  122. int main() {
  123. LinkList L;//链表头,是结构体指针类型
  124. LinkList search;
  125. CreateList2(L);//输入数据可以为3 4 5 6 7 9999(输入9999代表循环结束)
  126. PrintList(L);
  127. search=GetElem(L, 2);//查找链表第二个位置的元素值
  128. if (search != NULL) {
  129. printf("按序号查找成功\n");
  130. printf("%d\n",search->data);
  131. }
  132. search = LocateElem(L,6);//按值查询
  133. if (search != NULL) {
  134. printf("按值查找成功:%d\n", search->data);
  135. }
  136. ListFrontInsert(L,2,99);
  137. PrintList(L);
  138. //ListDelete(L, 4);
  139. //PrintList(L);
  140. return 0;
  141. }