线性表的特点

线性结构的特定是:在数据的非空有限集中

  1. 存在唯一的一个被称做第一个的数据元素
  2. 存在唯一的一个被称为最后一个的数据元素
  3. 除了第一个外,集合中所有数据元素都由一个前驱
  4. 除了最后一个外,集合中所有的元素都有一个后继

线性表的顺序表示和实现

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define TRUE 1
  4. #define FALSE 0
  5. #define OK 1
  6. #define ERROR 0
  7. #define INFEASIBLE -1 // 英文翻译,不可行,不可能
  8. #define OVERFLOW -2 // 英文翻译,溢出
  9. typedef int Status;
  10. typedef int ElemType;
  11. // #define ElemType int
  12. #define LIST_INIT_SIZE 5 // 线性表初始分配量
  13. #define LISTINCREMENT 10 // 增量
  14. typedef struct {
  15. ElemType * elem; // 线性表基地址
  16. int length; // 列表长度
  17. int listsize; // 当前分配存储容量(以sizeof(ElemType)为单位)
  18. } SqList;
  19. Status InitList_Sq(SqList *L) { // 创建一个线性表
  20. (*L).elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
  21. if (!(*L).elem) { // 存储分配失败
  22. printf("创建失败\n");
  23. exit(OVERFLOW);
  24. }
  25. (*L).length = 0; // 初始长度
  26. (*L).listsize = LIST_INIT_SIZE; // 初始存储容量
  27. printf("创建成功\n");
  28. return OK;
  29. }
  30. Status ListInsert_Sq(SqList *L, int i, ElemType e) {
  31. if (i < 1 || i > (*L).length + 1) {
  32. printf("插入失败\n");
  33. return ERROR;
  34. }
  35. if ((*L).length >= (*L).listsize) { // 存储空间已满,分配新内存
  36. ElemType * newbase = (ElemType *)realloc((*L).elem, ((*L).listsize + LISTINCREMENT) * sizeof(ElemType));
  37. if (!newbase) {
  38. exit(OVERFLOW);
  39. }
  40. (*L).elem = newbase;
  41. (*L).listsize += LISTINCREMENT;
  42. }
  43. ElemType *q = &((*L).elem[i - 1]);
  44. printf("%p\n", q);
  45. for (ElemType *p = &((*L).elem[(*L).length - 1]); p >= q; p--) {
  46. // 插入位置及之后的元素右移
  47. *(p+1) = *p;
  48. }
  49. *q = e;
  50. ++(*L).length;
  51. printf("插入成功\n");
  52. return OK;
  53. }
  54. Status ListDelete_Sq(SqList *L, int i, ElemType *e) {
  55. // 假设原有2位[1,3] i = 1;
  56. // *p 指向第一个元素
  57. // 通过指针给e赋值,相当于将被删除的元素值返回
  58. // *q 指向最后一个元素
  59. // 首先++p,现在p指向最后一个元素
  60. // p <= q,p和q相等,将值左移一位
  61. // p++ 后,指针出界,p > q, 不满足条件
  62. if (i < 1 || i > (*L).length + 1) {
  63. printf("删除失败\n");
  64. return ERROR;
  65. }
  66. ElemType *p = &((*L).elem[i - 1]);
  67. *e = *p;
  68. ElemType *q = (*L).elem + (*L).length; // 指向最后一个元素 相当于 [] + length
  69. for (++p; p <= q; ++p) {
  70. *(p - 1) = *p;
  71. }
  72. --(*L).length;
  73. printf("删除成功\n");
  74. return OK;
  75. }
  76. int LocateElem_Sq(SqList *L, ElemType e, Status (* compare)(ElemType, ElemType)) {
  77. int i = 1;
  78. ElemType *p = (*L).elem;
  79. while(i <= (*L).length && !(* compare)(*p++, e)) {
  80. ++i;
  81. }
  82. if (i <= (*L).length) {
  83. return i;
  84. }
  85. return 0;
  86. }
  87. Status compare(ElemType x, ElemType y) {
  88. printf("%d,%d\n", x, y);
  89. return x == y ? TRUE : FALSE;
  90. }
  91. Status DestroyList(SqList *L) {
  92. free((*L).elem);
  93. (*L).elem = NULL;
  94. printf("线性表被释放!表长度:%d\n", L->length);
  95. printf("线性表被释放!表空间:%lu字节\n", L->listsize * sizeof(ElemType));
  96. L->length = 0;
  97. L->listsize = 0;
  98. return OK;
  99. }
  100. int ListLength(SqList *L) {
  101. return (*L).length;
  102. }
  103. Status ListEmpty(SqList *L) {
  104. if ((*L).elem == NULL) {
  105. return TRUE;
  106. }
  107. return FALSE;
  108. }
  109. Status ClearList(SqList *L) {
  110. if ((*L).elem != NULL) {
  111. free((*L).elem);
  112. (*L).elem = NULL;
  113. }
  114. (*L).elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
  115. if (!(*L).elem) { // 存储分配失败
  116. printf("重置为空表\n");
  117. exit(OVERFLOW);
  118. }
  119. L->length = 0;
  120. L->listsize = LIST_INIT_SIZE;
  121. return OK;
  122. }
  123. int main(){
  124. Status InitList_Sq(SqList *L);
  125. Status ListInsert_Sq(SqList *L, int i, ElemType e);
  126. Status ListDelete_Sq(SqList *L, int i, ElemType *e);
  127. Status compare(ElemType x, ElemType y);
  128. int LocateElem_Sq(SqList *L, ElemType e, Status (* compare)(ElemType, ElemType));
  129. Status DestroyList(SqList *L);
  130. SqList *list;
  131. // 创建线性表
  132. InitList_Sq(list);
  133. printf("length=%d\n", (*list).length);
  134. // 数据插入线性表
  135. ListInsert_Sq(list, (*list).length + 1, 1990);
  136. ListInsert_Sq(list, (*list).length + 1, 1991);
  137. ListInsert_Sq(list, (*list).length + 1, 1991);
  138. ListInsert_Sq(list, (*list).length + 1, 1991);
  139. ListInsert_Sq(list, (*list).length + 1, 1991);
  140. ListInsert_Sq(list, (*list).length + 1, 1991);
  141. ListInsert_Sq(list, (*list).length + 1, 1991);
  142. ListInsert_Sq(list, (*list).length + 1, 1991);
  143. printf("length=%d\n", (*list).length);
  144. // 删除线性表的数据
  145. ElemType e;
  146. ListDelete_Sq(list, 2, &e);
  147. // printf("e=%d\n", e);
  148. printf("listsize=%d\n", (*list).listsize);
  149. e = 1991;
  150. int index = LocateElem_Sq(list, e, *compare);
  151. printf("index=%d\n", index);
  152. DestroyList(list);
  153. printf("ListEmpty=%d\n", ListEmpty(list));
  154. printf("ClearList=%d\n", ClearList(list));
  155. return 0;
  156. }

线性链表的实现

指针型

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. typedef int Status;
  4. typedef int ElemType;
  5. typedef struct LNode {
  6. ElemType data;
  7. int length;
  8. struct LNode *next;
  9. }LNode, *LinkList;
  10. #define TRUE 1
  11. #define FALSE 0
  12. #define OK 1
  13. #define ERROR 0
  14. #define INFEASIBLE -1 // 英文翻译,不可行,不可能
  15. #define OVERFLOW -2 // 英文翻译,溢出
  16. Status CreateList_L(LinkList *L, int n) {
  17. (*L) = (LinkList)malloc(sizeof(LNode));
  18. (*L) -> next = NULL;
  19. (*L) -> length = 0;
  20. int i;
  21. LinkList q;
  22. for (i = n; i > 0; --i) {
  23. LinkList p = (LinkList)malloc(sizeof(LNode));
  24. printf("请输入数据:");
  25. scanf("%d", &p -> data);
  26. if ((*L) -> next == NULL) {
  27. p -> next = (*L) -> next;
  28. (*L) -> next = p;
  29. q = p;
  30. (*L) -> length += 1;
  31. } else {
  32. q -> next = p;
  33. p -> next = NULL;
  34. q = p;
  35. (*L) -> length += 1;
  36. }
  37. }
  38. return OK;
  39. }
  40. ElemType *GetElem_L(LinkList L, int i) {
  41. LinkList p = L -> next;
  42. int j = 1;
  43. while(p && j < i) {
  44. p = p -> next;
  45. ++j;
  46. }
  47. if (!p || j > i) {
  48. return ERROR;
  49. }
  50. return &(p -> data);
  51. }
  52. void printAll(LinkList L) {
  53. LinkList p = L -> next;
  54. int i = 1;
  55. while(p != NULL) {
  56. printf("item[%d]=%d\n",i, p -> data);
  57. i++;
  58. p = p -> next;
  59. }
  60. }
  61. Status ListInsert_L(LinkList L, int i, ElemType e) {
  62. LinkList p = L -> next;
  63. int j = 0;
  64. while (p && j < i - 1) {
  65. p = p -> next;
  66. ++j;
  67. }
  68. if (!p || j > i - 1) {
  69. return ERROR;
  70. }
  71. LinkList s = (LinkList)malloc(sizeof(LNode));
  72. s -> data = e;
  73. s -> next = p -> next;
  74. p -> next = s;
  75. L -> length += 1;
  76. return OK;
  77. }
  78. Status ListDelete_L(LinkList L, int i, ElemType *e) {
  79. LinkList p = L -> next;
  80. int j = 1;
  81. while (p && j < i - 1) {
  82. p = p -> next;
  83. ++j;
  84. }
  85. if (!(p -> next) || j > i - 1) {
  86. return ERROR;
  87. }
  88. LinkList q = p -> next; // p = 要被删除的那个的前一个
  89. p -> next = q -> next;
  90. *e = q -> data;
  91. L -> length -= 1;
  92. free(q);
  93. return OK;
  94. }
  95. int main(){
  96. Status CreateList_L(LinkList *L, int n);
  97. ElemType *GetElem_L(LinkList L, int i);
  98. LinkList list;
  99. CreateList_L(&list, 2);
  100. printf("item=%d\n", *GetElem_L(list, 1));
  101. printf("item=%d\n", *GetElem_L(list, 2));
  102. printf("length=%d\n", (*list).length);
  103. ListInsert_L(list, (*list).length, 18);
  104. printAll(list);
  105. ElemType e;
  106. printf("length=%d\n", (*list).length);
  107. ListDelete_L(list, (*list).length, &e);
  108. printf("e=%d\n", e);
  109. printAll(list);
  110. return 0;
  111. }

静态链表(用数组来表示的)

以i代替动态指针p,类似与 p = p -> next

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define MAXSIZE 10
  4. typedef int ElemType;
  5. #define format_elem "%d"
  6. typedef struct {
  7. ElemType data;
  8. int cur; // 存储下标
  9. } component, SLinkList[MAXSIZE];
  10. void InitSpace_SL(SLinkList *S) { // 初始化
  11. int i = 0;
  12. for (i = 0; i < MAXSIZE - 1; ++i) {
  13. S[i] -> cur = i + 1;
  14. }
  15. S[MAXSIZE - 1]-> cur = 0;
  16. }
  17. int Malloc_SL(SLinkList *S) { // 分配空间
  18. int i = S[0]-> cur;
  19. if (S[0]-> cur) {
  20. S[0]-> cur = S[i]-> cur;
  21. }
  22. return i;
  23. }
  24. void Free_SL(SLinkList *S, int k) { // 释放空间
  25. }
  26. void printAll(SLinkList *S, int r) {
  27. S[0]-> cur = S[r] -> cur;
  28. while(S[0] -> cur != 0) {
  29. printf("item[%d]=%d\n", r, S[r] -> data);
  30. r = S[r] -> cur; // 指针下移
  31. S[0] -> cur = r; // 指针下移
  32. }
  33. }
  34. int main() {
  35. SLinkList list;
  36. InitSpace_SL(&list); // 初始化
  37. int i = Malloc_SL(&list); // 获取头指针位置 i = 1
  38. int r = i; // r 是头指针
  39. (&list)[i] -> data = 11; // (&list)[i] -> cur = 2
  40. i = Malloc_SL(&list); // 指针后移 i = 2
  41. (&list)[i] -> data = 22; // (&list)[i] -> cur = 3
  42. (&list)[i] -> cur = 0; // (&list)[i] -> cur = 0
  43. printAll(&list, r);
  44. }

循环链表

循环链表和指针型链表表现一致,只是最后一个节点不的next不指向NULL,而是指向头指针

双向链表

  1. typedef struct DcLNode {
  2. ElemType data;
  3. struct DuLNode *prior; // 指向上一个节点
  4. struct DuLNode *next; // 指向下一个节点
  5. }
  6. d = d -> next -> prior = d -> prior - next;