一)声明
新手上路。如果有不对的,不合理的地方,编码风格,算法思路有待改进的地方,还请各位大神多多指点。
二)简介
本文中采用动态开辟内存的方法建立线性表,实现顺序表的基本操作。
此代码思路比较简单,毕竟只是简单的原理,没有具体的应用,仅仅作为入门学习的积累。
三)具体实现分析如下:
3.1)头文件定义如下:
1 #ifndef LinearList_SqList_h 2 #define LinearList_SqList_h 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 7 #define OK 1 8 #define ERROR 0 9 10 #define LIST_INIT_SIZE 100 11 #define SIZE_INCREMENT 10 12 13 typedef int Status; 14 typedef int ElemType; 15 16 typedef struct { 17 ElemType *pElem; 18 int nLength; 19 int nListSize; 20 }SqList; 21 22 23 void InitSqList(SqList *L); 24 Status InsertSqList(SqList *L, int nIndex, ElemType eValue); 25 Status AssignSqList(SqList *L); 26 Status DeleteSqList(SqList *L, int nIndex, ElemType *pValue); 27 Status ClearSqList(SqList *L); 28 Status DestroySqList(SqList *L); 29 Status LocateElem(SqList L, ElemType nValue); 30 Status PrintSqList(SqList L); 31 32 #endif
SqList.h
3.2)具体实现:
3.2.1)基本原则:
a)函数参数中,只要传递的是指针,函数内必须首先校验指针是否为空。
b)如果要对顺序表进行修改,那么必须进行地址传递,而不是值传递。
c)malloc申请的内存,一定要用free释放,并且释放之后,置指针为空,防止出现也指针。
3.2.2)具体代码思路:
a、InitSqList
动态申请空间,依此对顺序表的成员赋值。
b、InsertSqList (此处允许对空表进行插入)
思路:校验指针参数——》校验插入点——》校验顺序表是否已初始化——》校验顺序表是否已满——》遍历顺序表,找到插入点——》移动元素——》插入——》同时表长增加;
分析:其实真正的插入就是一行代码,但是为了保证插入后不影响其他元素的使用,必须移动元素;为了保证程序的健壮性,必须增加很多校验过程;
重点在于下标的计算。
2.1参数校验:指针是否为空;插入点是否非法
2.2顺序表校验:顺序表是否已初始化;对于插入而言,顺序表是否已满;
2.3当所有的校验完毕之后,寻找正确插入点,移动元素(从表尾向待插入点方向遍历),最后插入,增加表长;
(2.4)关于空表是否允许插入的问题:根据不同的需求和功能设定。如果不允许对空表插入,可以多加一层校验功能即可;(此处允许空表插入)
c、DeleteSqList (基本原理类似于Insert)
思路:校验指针参数——》校验删除点——》校验顺序表是否初始化——》校验顺序表是否为空——》遍历顺序表,寻找删除点——》移动元素——》删除——》同时表长自减;
分析:删除元素就是不断的移动元素,采用覆盖原理即可(从删除点向表尾方向遍历)。关键是下标的计算。
d、DestroySqList
思路:校验指针参数——》校验顺序表是否初始化——》释放申请的内存——》同时设置顺序表相关参数。
分析:重点在于参数的校验和free过后的指针应该置空。
3.3)具体代码如下:
1 #include "SqList.h" 2 3 void InitSqList(SqList *L) { 4 if (NULL == L) { 5 printf("Error parament."); 6 return ; 7 } 8 9 L->pElem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(SqList)); 10 if (NULL == L->pElem) { 11 printf("Error:Out of memory."); 12 return ; 13 } 14 15 L->nLength = 0; 16 L->nListSize = LIST_INIT_SIZE; 17 } 18 19 20 //Insert element to sqlist 21 Status InsertSqList(SqList *L, int nIndex, ElemType eValue) { 22 if (NULL == L) { 23 printf("Error parament."); 24 return ERROR; 25 } 26 27 if (NULL == L->pElem) { 28 printf("Error: The list is not initiated."); 29 return ERROR; 30 } 31 32 if (nIndex < 1 || nIndex > L->nLength + 1) { 33 printf("Error: Invalid insert point."); 34 return ERROR; 35 } 36 37 ElemType *pNewBase; 38 if (L->nLength >= L->nListSize) { 39 pNewBase = (ElemType*)realloc(L->pElem, (LIST_INIT_SIZE + SIZE_INCREMENT) * sizeof(ElemType)); 40 if (NULL == pNewBase) { 41 printf("Error:Out of memory."); 42 return OK; 43 } 44 //here can also write with ‘else‘. 45 //Logically no problem. But it takes effort to write the else and ‘{}‘. Efficiently not good choice 46 L->pElem = pNewBase; 47 L->nListSize += SIZE_INCREMENT; 48 } 49 50 ElemType *pInsert, *pLast; 51 pInsert = L->pElem + nIndex - 1; 52 pLast = L->pElem + L->nLength - 1; 53 54 55 while (pLast >= pInsert) { 56 *(pLast + 1) = *pLast; 57 pLast--; 58 } 59 60 *pInsert = eValue; 61 ++L->nLength; 62 63 return OK; 64 } 65 66 //Assign sqlist 67 Status AssignSqList(SqList *L) { 68 if (NULL == L) { 69 printf("Error parament."); 70 return ERROR; 71 } 72 73 if (NULL == L->pElem) { 74 printf("Error:The list is not initiated."); 75 return ERROR; 76 } 77 78 int nLength, nValue; 79 printf("Input the length:"); 80 scanf("%d", &nLength); 81 82 for (int i = 1; i <= nLength; i++) { 83 printf("Input the value:"); 84 scanf("%d", &nValue); 85 86 InsertSqList(L, i, nValue); 87 } 88 89 return OK; 90 } 91 92 //delete element from sqlist 93 Status DeleteSqList(SqList *L, int nIndex, ElemType *pValue) { 94 if (NULL == L || NULL == pValue) { 95 printf("Error parament."); 96 return ERROR; 97 } 98 99 if (NULL == L->pElem) { 100 printf("Error:The list is not initiated."); 101 return ERROR; 102 } 103 104 if (L->nLength <= 0) { 105 printf("Error:The list is empty.Can‘t delete."); 106 return ERROR; 107 } 108 109 if (nIndex < 1 || nIndex > L->nLength) { 110 printf("Error:Invalid delete index."); 111 return ERROR; 112 } 113 114 ElemType *pDelete, *pLast; 115 pDelete = L->pElem + nIndex - 1; 116 pLast = L->pElem + L->nLength - 1; 117 118 *pValue = *pDelete; 119 for (pDelete++; pDelete <= pLast; pDelete++) { 120 *(pDelete - 1) = *pDelete; 121 } 122 123 --L->nLength; 124 125 return OK; 126 } 127 128 //clear sqlist 129 Status ClearSqList(SqList *L) { 130 if (NULL == L) { 131 printf("Error parament."); 132 return ERROR; 133 } 134 135 if (NULL == L->pElem) { 136 printf("Error: The list is not initiated."); 137 return ERROR; 138 } 139 140 L->nLength = 0; 141 142 return OK; 143 } 144 145 //destroy sqlist 146 Status DestroySqList(SqList *L) { 147 if (NULL == L) { 148 printf("Error parament."); 149 return ERROR; 150 } 151 152 if (NULL == L->pElem) { 153 printf("Error:The list is not initiated."); 154 return ERROR; 155 } 156 157 free(L->pElem); 158 L->pElem = NULL; 159 L->nLength = 0; 160 L->nListSize = 0; 161 162 return OK; 163 } 164 165 //locate element from sqlist 166 Status LocateElem(SqList L, ElemType nValue) { 167 if (NULL == L.pElem) { 168 printf("Error:The list is not initiated."); 169 return ERROR; 170 } 171 172 if (L.nLength <= 0) { 173 printf("Error:The list is empty."); 174 return ERROR; 175 } 176 177 int nIndex; 178 ElemType *pLocate = L.pElem; 179 180 for (nIndex = 1; nIndex <= L.nLength; nIndex++) { 181 if (nValue == *pLocate) { 182 printf("Located succeeded."); 183 return nIndex; 184 } 185 pLocate++; 186 } 187 188 return ERROR; 189 } 190 191 192 //Print sqlist 193 Status PrintSqList(SqList L) { 194 if (NULL == L.pElem) { 195 printf("Error:The list is not initiated."); 196 return ERROR; 197 } 198 199 if (L.nLength <= 0) { 200 printf("The list is empty."); 201 return ERROR; 202 } 203 204 printf("The list is as follows:"); 205 for (int i = 1; i <= L.nLength; i++) { 206 printf("%d ", *L.pElem); 207 L.pElem++; 208 } 209 210 printf("\n"); 211 return OK; 212 }
SqList.c