当前位置:   article > 正文

数据结构(初阶)——顺序表、链表_sldatetype x

sldatetype x

一、顺序表

SeqList.h

  1. #pragma once
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<stdlib.h>
  5. #include<errno.h>
  6. #include<assert.h>
  7. typedef int SLDataType;
  8. // 顺序表的动态存储
  9. typedef struct SeqList
  10. {
  11. SLDataType* array; // 指向动态开辟的数组
  12. size_t size; // 有效数据个数
  13. size_t capicity; // 容量空间的大小
  14. }SeqList;
  15. SeqList SL;
  16. // 基本增删查改接口
  17. // 顺序表初始化
  18. void SeqListInit(SeqList* psl);
  19. // 检查空间,如果满了,进行增容
  20. void CheckCapacity(SeqList* psl);
  21. // 顺序表尾插
  22. void SeqListPushBack(SeqList* psl, SLDataType x);
  23. // 顺序表尾删
  24. void SeqListPopBack(SeqList* psl);
  25. // 顺序表头插
  26. void SeqListPushFront(SeqList* psl, SLDataType x);
  27. // 顺序表头删
  28. void SeqListPopFront(SeqList* psl);
  29. // 顺序表查找
  30. int SeqListFind(SeqList* psl, SLDataType x);
  31. // 顺序表在pos位置插入x
  32. void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);
  33. // 顺序表删除pos位置的值
  34. void SeqListErase(SeqList* psl, size_t pos);
  35. // 顺序表销毁
  36. void SeqListDestory(SeqList* psl);
  37. // 顺序表打印
  38. void SeqListPrint(SeqList* psl);
  39. //顺序表修改
  40. void SLModify(SeqList* psl, size_t pos, SLDataType x);

SeqList.c

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include "SeqList.h"
  3. // 顺序表初始化
  4. void SeqListInit(SeqList* psl) {
  5. assert(psl);
  6. psl->capicity = 0;
  7. psl->size = 0;
  8. psl->array = NULL;
  9. }
  10. //顺序表打印
  11. void SeqListPrint(SeqList* psl) {
  12. assert(psl);
  13. for (int i = 0; i < psl->size; i++) {
  14. printf("%d ", psl->array[i]);
  15. }
  16. }
  17. // 顺序表头插
  18. void SeqListPushFront(SeqList* psl, SLDataType x) {
  19. assert(psl);
  20. //检查空间是否足够
  21. CheckCapacity(&psl);
  22. int temp_size = psl->size;
  23. while (temp_size > 0) {
  24. psl->array[temp_size] = psl->array[temp_size-1];
  25. temp_size--;
  26. }
  27. psl->array[0] = x;
  28. psl->size++;
  29. }
  30. // 顺序表尾插
  31. void SeqListPushBack(SeqList* psl, SLDataType x) {
  32. assert(psl);
  33. //检查空间是否足够
  34. CheckCapacity(&psl);
  35. psl->array[psl->size] = x;
  36. psl->size++;
  37. }
  38. // 顺序表销毁
  39. void SeqListDestory(SeqList* psl) {
  40. assert(psl);
  41. free(psl->array);
  42. psl->array = NULL;
  43. psl->capicity = 0;
  44. psl->size = 0;
  45. }
  46. // 检查空间,如果满了,进行增容
  47. void CheckCapacity(SeqList** psl) {
  48. if ((*psl)->capicity == 0) {
  49. SLDataType* temp = NULL;
  50. (*psl)->capicity = 4 * sizeof(SLDataType);
  51. temp = (SLDataType)malloc((*psl)->capicity);
  52. if (temp == NULL) {
  53. perror(CheckCapacity);
  54. return 0;
  55. }
  56. (*psl)->array = temp;
  57. return;
  58. }
  59. if ((*psl)->capicity <= (*psl)->size*sizeof(SLDataType)) {
  60. (*psl)->capicity *= 2;
  61. SLDataType* temp = NULL;
  62. //检查开辟是否成功
  63. temp = (SLDataType)realloc((*psl)->array,(*psl)->capicity);
  64. if (temp == NULL) {
  65. perror(CheckCapacity);
  66. return 0;
  67. }
  68. (*psl)->array = temp;
  69. }
  70. }
  71. // 顺序表尾删
  72. void SeqListPopBack(SeqList* psl) {
  73. assert(psl);
  74. psl->size--;
  75. }
  76. // 顺序表头删
  77. void SeqListPopFront(SeqList* psl) {
  78. assert(psl);
  79. int temp_size = 1;
  80. while (temp_size <= psl->size) {
  81. psl->array[temp_size-1] = psl->array[temp_size];
  82. temp_size++;
  83. }
  84. psl->size--;
  85. }
  86. // 顺序表查找
  87. int SeqListFind(SeqList* psl, SLDataType x) {
  88. assert(psl);
  89. //找到返回下标
  90. for (int i = 0; i < psl->size; i++) {
  91. if (psl->array[i] == x) {
  92. return i;
  93. }
  94. }
  95. //没找到返回-1
  96. return -1;
  97. }
  98. // 顺序表删除pos位置的值
  99. void SeqListErase(SeqList* psl, size_t pos) {
  100. assert(psl);
  101. assert(pos < psl->size);
  102. if (pos >= psl->size) {
  103. printf("删除超出范围限制");
  104. return ;
  105. }
  106. while (pos < psl->size) {
  107. psl->array[pos] = psl->array[pos + 1];
  108. pos++;
  109. }
  110. psl->size--;
  111. }
  112. // 顺序表在pos位置插入x
  113. void SeqListInsert(SeqList* psl, size_t pos, SLDataType x) {
  114. assert(psl);
  115. assert(pos <= psl->size);
  116. CheckCapacity(&psl);
  117. int temp = psl->size;
  118. while (temp > pos) {
  119. psl->array[temp] = psl->array[temp - 1];
  120. temp--;
  121. }
  122. psl->array[pos] = x;
  123. psl->size++;
  124. }
  125. //修改
  126. void SLModify(SeqList* psl, size_t pos, SLDataType x) {
  127. assert(psl);
  128. assert(pos < psl->size);
  129. psl->array[pos] = x;
  130. }

二.单链表

单链表.h

  1. #pragma once
  2. #include<stdio.h>
  3. #include<assert.h>
  4. #include<stdlib.h>
  5. typedef int SLTDateType;
  6. typedef struct SListNode
  7. {
  8. SLTDateType data;
  9. struct SListNode* next;
  10. }SListNode;
  11. // 动态申请一个结点
  12. SListNode* BuySListNode(SLTDateType x);
  13. // 单链表打印
  14. void SListPrint(SListNode* plist);
  15. // 单链表尾插
  16. void SListPushBack(SListNode** pplist, SLTDateType x);
  17. // 单链表的头插
  18. void SListPushFront(SListNode** pplist, SLTDateType x);
  19. // 单链表的尾删
  20. void SListPopBack(SListNode** pplist);
  21. // 单链表头删
  22. void SListPopFront(SListNode** pplist);
  23. // 单链表查找
  24. SListNode* SListFind(SListNode* plist, SLTDateType x);
  25. // 单链表在pos位置之后插入x
  26. // 分析思考为什么不在pos位置之前插入?
  27. void SListInsertAfter(SListNode* pos, SLTDateType x);
  28. // 单链表 之前插入(难)
  29. void SListInsertBefore(SListNode* pos, SLTDateType x);
  30. // 单链表删除pos位置之后的值
  31. // 分析思考为什么不删除pos位置?
  32. void SListEraseAfter(SListNode* pos);
  33. // 单链表销毁
  34. void SLlistDestory(SListNode* phead);
  35. //单链表删除当前位置
  36. void SListErase(SListNode* pos);

单链表.c

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include"单链表.h"
  3. SListNode* BuySListNode(SLTDateType x) {
  4. SListNode* temp = (SListNode*)malloc(sizeof(SListNode));
  5. if (temp == NULL) {
  6. perror("malloc fail");
  7. exit(-1);
  8. }
  9. SListNode* newnode = temp;
  10. temp = NULL;
  11. newnode->data = x;
  12. newnode->next = NULL;
  13. return newnode;
  14. }
  15. // 单链表打印
  16. void SListPrint(SListNode* phead) {
  17. SListNode* cur = phead;
  18. while (cur) {
  19. printf("%d->", cur->data);
  20. cur = cur->next;
  21. }
  22. printf("NULL\n");
  23. }
  24. // 单链表的头插
  25. void SListPushFront(SListNode** pphead, SLTDateType x) { //改变一级指针就需要一级指针的地址,所以传入二级指针
  26. assert(pphead);
  27. SListNode* newnode = BuySListNode(x);
  28. newnode->next = *pphead;
  29. *pphead = newnode;
  30. }
  31. // 单链表尾插
  32. void SListPushBack(SListNode** pphead, SLTDateType x) {
  33. assert(pphead);
  34. //单链表不为空
  35. if (* pphead == NULL ) {
  36. SListNode* next = BuySListNode(x);
  37. *pphead = next;
  38. }//单链表为空
  39. else {
  40. SListNode* cur = *pphead;
  41. while (cur->next != NULL) {
  42. cur = cur->next;
  43. }
  44. SListNode* next = BuySListNode(x);
  45. cur->next = next;
  46. }
  47. }
  48. // 单链表头删
  49. void SListPopFront(SListNode** pphead) {
  50. assert(pphead);
  51. if (*pphead == NULL) {
  52. return;
  53. }
  54. SListNode* del = *pphead;
  55. *pphead = (*pphead)->next;
  56. free(del);
  57. del = NULL;
  58. }
  59. // 单链表的尾删
  60. void SListPopBack(SListNode** pphead) {
  61. assert(pphead);
  62. if (*pphead == NULL) {
  63. return;
  64. }
  65. if ((*pphead)->next == NULL) {
  66. free(*pphead);
  67. *pphead = NULL;
  68. return;
  69. }
  70. SListNode* cur = *pphead;
  71. while (cur->next->next != NULL) {
  72. cur = cur->next;
  73. }
  74. free(cur->next);
  75. cur->next = NULL;
  76. }
  77. // 单链表查找
  78. SListNode* SListFind(SListNode* pphead, SLTDateType x) {
  79. assert(pphead);
  80. SListNode* cur = pphead;
  81. while (cur) {
  82. if (x == cur->data) {
  83. printf("找到了\n");
  84. return cur;
  85. }
  86. else {
  87. cur = cur->next;
  88. }
  89. }
  90. return NULL;
  91. }
  92. //单链表在某位置之后插入
  93. void SListInsertAfter(SListNode** pphead,SListNode* pos, SLTDateType x) {
  94. assert(pphead);
  95. if (*pphead == NULL) {
  96. SListPushFront(pphead, x);
  97. return;
  98. }
  99. SListNode* newcode = BuySListNode(x);
  100. newcode->next = pos->next;//注意这两行的顺序
  101. pos->next = newcode;
  102. }
  103. // 单链表 之前插入(难)
  104. void SListInsertBefore(SListNode** pphead, SListNode* pos, SLTDateType x) {
  105. assert(pos);
  106. assert(pphead);
  107. if (*pphead == NULL) {
  108. SListPushFront(pphead, x);
  109. return;
  110. }
  111. //方法一:找到前一项的next
  112. SListNode* cur = *pphead;
  113. if (pos == pphead) {
  114. SListPushFront(pphead, x);
  115. return;
  116. }
  117. while (cur->next != pos) {
  118. cur = cur->next;
  119. //找不到,说明pos传错了
  120. assert(cur);
  121. }
  122. SListNode* newcode = BuySListNode(x);
  123. newcode->next = pos;
  124. cur->next = newcode;
  125. //方法二 顺序法交换
  126. //SListNode* newcode = BuySListNode(pos->data);
  127. //pos->data = x;
  128. }
  129. // 单链表删除pos位置之后的值
  130. // 分析思考为什么不删除pos位置?
  131. void SListEraseAfter(SListNode** pphead, SListNode* pos) {
  132. assert(pphead);
  133. assert(pos);
  134. if (pos->next == NULL) {
  135. SListPopBack(pphead);
  136. return;
  137. }
  138. SListNode* cur = pos->next;
  139. pos->next = pos->next->next;
  140. free(cur);
  141. }
  142. //单链表删除当前位置
  143. void SListErase(SListNode** pphead, SListNode* pos) {
  144. assert(pphead && pos);
  145. if (pos == *pphead) {
  146. SListPopFront(pphead);
  147. return;
  148. }
  149. SListNode* cur = pos->next->next;
  150. pos->data = pos->next->data;
  151. free(pos->next);
  152. pos->next = cur;
  153. }
  154. // 单链表销毁
  155. void SLlistDestory(SListNode** pphead) {
  156. assert(pphead);
  157. SListNode* cur = pphead;
  158. SListNode* next = pphead;
  159. while (cur) {
  160. next = cur->next;
  161. free(cur);
  162. cur = next;
  163. }
  164. pphead = NULL;
  165. }

三.带头双向循环链表

List.h

  1. #pragma once
  2. #include<stdio.h>
  3. #include<assert.h>
  4. #include<stdlib.h>
  5. typedef int LTDataType;
  6. typedef struct ListNode
  7. {
  8. LTDataType _data;
  9. struct ListNode* next;
  10. struct ListNode* prev;
  11. }ListNode;
  12. // 创建返回链表的头结点.
  13. ListNode* ListCreate();
  14. //双向链表创造一个新节点
  15. ListNode* ListBuyNode(LTDataType x);
  16. // 双向链表打印
  17. void ListPrint(ListNode* plist);
  18. // 双向链表尾插
  19. void ListPushBack(ListNode* plist, LTDataType x);
  20. // 双向链表头插
  21. void ListPushFront(ListNode* plist, LTDataType x);
  22. // 双向链表尾删
  23. void ListPopBack(ListNode* plist);
  24. // 双向链表头删
  25. void ListPopFront(ListNode * plist);
  26. // 双向链表查找
  27. ListNode* ListFind(ListNode* plist, LTDataType x);
  28. // 双向链表在pos的前面进行插入
  29. void ListInsert(ListNode* pos, LTDataType x);
  30. // 双向链表删除pos位置的结点
  31. void ListErase(ListNode* pos);
  32. // 双向链表销毁
  33. void ListDestory(ListNode* plist);

List.c

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include"List.h"
  3. // 创建返回链表的头结点.
  4. ListNode* ListCreate() {
  5. ListNode* ListGuard = (ListNode*)malloc(sizeof(ListNode));
  6. if (ListGuard == NULL) {
  7. perror("ListGuard malloc fai");
  8. exit(-1);
  9. }
  10. ListGuard->next = ListGuard;
  11. ListGuard->prev = ListGuard;
  12. return ListGuard;
  13. }
  14. // 双向链表打印
  15. void ListPrint(ListNode* plist) {
  16. assert(plist);
  17. ListNode* head = plist;
  18. ListNode* cur = head->next;
  19. printf("head<=>");
  20. while (cur != head) {
  21. printf("%d<=>", cur->_data);
  22. cur = cur->next;
  23. }
  24. printf("\n");
  25. }
  26. //双向链表创造一个新节点
  27. ListNode* ListBuyNode(LTDataType x) {
  28. ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
  29. if (newNode == NULL) {
  30. perror("newNode malloc fail");
  31. exit(-1);
  32. }
  33. newNode->next = NULL;
  34. newNode->prev = NULL;
  35. newNode->_data = x;
  36. return newNode;
  37. }
  38. // 双向链表尾插
  39. void ListPushBack(ListNode* plist, LTDataType x) {
  40. assert(plist);
  41. ListNode* tail = plist->prev;
  42. ListNode* newNode = ListBuyNode(x);
  43. //节点四步走 注意语句顺序!
  44. newNode->next = plist;
  45. plist->prev = newNode;
  46. tail->next = newNode;
  47. newNode->prev = tail;
  48. }
  49. // 双向链表头插
  50. void ListPushFront(ListNode* plist, LTDataType x) {
  51. assert(plist);
  52. ListNode* first = plist->next;
  53. ListNode* newNode = ListBuyNode(x);
  54. //节点四步走 注意语句顺序!
  55. first->prev = newNode;
  56. newNode->next = first;
  57. plist->next = newNode;
  58. newNode->prev = plist;
  59. }
  60. //检查双向列表是否为空
  61. int CheckList(ListNode* plist) {
  62. assert(plist);
  63. //返回“真”为空 返回"假"为非空;
  64. return plist->next == plist->prev;
  65. }
  66. // 双向链表尾删
  67. void ListPopBack(ListNode* plist) {
  68. assert(plist);
  69. assert(!CheckList(plist));
  70. ListNode* tail = plist->prev;
  71. //节点链接
  72. tail->prev->next = plist;
  73. plist->prev = tail->prev;
  74. //释放
  75. free(tail);
  76. }
  77. // 双向链表头删
  78. void ListPopFront(ListNode* plist) {
  79. assert(plist);
  80. assert(!CheckList(plist));
  81. ListNode* first = plist->next;
  82. //节点链接
  83. plist->next = first->next;
  84. first->next->prev = plist;
  85. //释放
  86. free(first);
  87. }
  88. // 双向链表查找
  89. ListNode* ListFind(ListNode* plist, LTDataType x) {
  90. assert(plist);
  91. if (CheckList(plist)) {
  92. printf("链表为NULL,无法查找有效数据\n");
  93. exit(-1);
  94. }
  95. ListNode* cur = plist->next;
  96. while (cur != plist) {
  97. if (cur->_data == x) {
  98. printf("找到啦\n");
  99. return cur;
  100. }
  101. cur = cur->next;
  102. }
  103. return NULL;
  104. }
  105. // 双向链表在pos的前面进行插入
  106. void ListInsert(ListNode* pos, LTDataType x) {
  107. assert(pos);
  108. ListNode* first = pos->prev;
  109. ListNode* second = pos;
  110. ListNode* newNode = ListBuyNode(x);
  111. newNode->next = second;
  112. second->prev = newNode;
  113. first->next = newNode;
  114. newNode->prev = first;
  115. }
  116. // 双向链表删除pos位置的结点
  117. void ListErase(ListNode* pos) {
  118. assert(pos);
  119. ListNode* first = pos->prev;
  120. ListNode* del = pos;
  121. ListNode* second = pos->next;
  122. first->next = second;
  123. second->prev = first;
  124. free(del);
  125. }
  126. // 双向链表销毁
  127. void ListDestory(ListNode* plist) {
  128. assert(plist);
  129. ListNode* cur = plist->next;
  130. ListNode* next = NULL;
  131. plist->next = NULL;
  132. while (cur != NULL) {
  133. next = cur->next;
  134. free(cur);
  135. cur = next;
  136. }
  137. printf("销毁成功\n");
  138. }

四、顺序表、链表 oj

 顺序表

1. 原地移除数组中所有的元素 val ,要求时间复杂度为 O(N) ,空间复杂度为 O(1)
2. 删除排序数组中的重复项。
3. 合并两个有序数组。

力扣

链表

1. 删除链表中等于给定值 val 的所有结点  力扣
2. 反转一个单链表。
3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则
返回第二个中间结点。
4. 输入一个链表,输出该链表中倒数第 k 个结点。
5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有
结点组成的。
6. 编写代码,以给定值 x 为基准将链表分割成两部分,所有小于 x 的结点排在大于或等于 x 的结
7. 链表的回文结构。 链表的回文结构_牛客题霸_牛客网
8. 输入两个链表,找出它们的第一个公共结点。 力扣
9. 给定一个链表,判断链表中是否有环。 力扣
【思路】
快慢指针,即慢指针一次走一步,快指针一次走两步,两个指针从链表其实位置开始运行,
如果链表
带环则一定会在环中相遇,否则快指针率先走到链表的末尾。比如:陪女朋友到操作跑步减
肥。
10. 给定一个链表,返回链表开始入环的第一个结点。 如果链表无环,则返回 NULL 力扣
11. 给定一个链表,每个结点包含一个额外增加的随机指针,该指针可以指向链表中的任何结点
或空结点。
要求返回这个链表的深度拷贝。 力扣
12. 其他 。 ps :链表的题当前因为难度及知识面等等原因还不适合我们当前学习,以后大家自己
顺序表优点:
1.尾插、尾删效率高。
2.可以随机访问。.
(了解)3.cpu高速缓存命中率更高(相比链表)
顺序表缺点:
1.头部中部插入效率低——O(N)
2.扩容 ——性能消耗,空间浪费
链表优点:
1.任意插入删除都很方便
2.扩容——不存在空间浪费(按需申请空间)
链表缺点:
1.扩容——每次都要申请malloc浪费了时间
2.不能随机访问

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/926407
推荐阅读
相关标签
  

闽ICP备14008679号