带头结点的单链表实现
LinkList.h
1 /********************************************************************* 2 *: 3 *: Author: dspeeding 4 *: Copyright (c) 2013, dspeeding 5 *: 6 *: Created at: 2013.08.06 7 *: Last modified: 2013.08.06 8 *: 9 *: Introduction: 线性表链式实现 10 *: 11 *: 注:ElemType类型 不能进行深拷贝,请留意 12 *: 如使用 TraverseList 函数 则需要自己实现Visit函数 13 *: 如使用 SortList 函数 则需要自己实现Compare函数 14 *: SortList 使用简单冒泡排序算法实现 15 *: 16 *:*********************************************************************/ 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 21 //定义数据类型为int型 22 typedef int ElemType; 23 24 25 typedef struct LNode{ 26 ElemType data; //数据 27 struct LNode *next; //下一指针 28 }LNode; 29 30 typedef LNode* LinkList; 31 typedef LinkList* PLinkList; 32 33 //定义数据类型的打印函数 34 typedef void (*Visit)(ElemType*); 35 36 //定义数据类型的比较函数 37 typedef int (*Compare)(ElemType*, ElemType*); 38 39 /**************************************** 40 Purpose : 初始化线性表 41 Input : L -- 线性表指针 42 Return : 0 --OK 43 -1 --FAIL 44 *****************************************/ 45 int InitList(PLinkList L); 46 47 48 /**************************************** 49 Purpose : 清空链表 50 Input : L -- 线性表指针 51 Return : None 52 *****************************************/ 53 void ClearList(PLinkList L); 54 55 /**************************************** 56 Purpose : 线性表长度 57 Input : L -- 线性表指针 58 Return : 线性表长度 如果是-1,则表示出错 59 *****************************************/ 60 int ListLength(PLinkList L); 61 62 /**************************************** 63 Purpose : 取链表中第nPos个元素 64 Input : L -- 线性表指针 65 nPos -- 位置 66 val -- 要取到的元素 67 Return : 0 --OK 68 -1 --FAIL 69 *****************************************/ 70 int GetElem(PLinkList L, int nPos, ElemType *val); 71 72 /**************************************** 73 Purpose : 在线性表中第nPos个位置插入新元素 74 Input : L -- 线性表指针 75 nPos -- 位置[1,ListLength(L)+1] 76 val -- 要插入的元素 77 Return : 0 --OK 78 -1 --FAIL 79 *****************************************/ 80 int InsertList(PLinkList L, int nPos, ElemType *val); 81 82 /**************************************** 83 Purpose : 在线性表中第nPos个位置删除元素 84 Input : L -- 线性表指针 85 nPos -- 位置[1,ListLength(L)] 86 val -- 数据 87 Return : 0 --OK 88 -1 --FAIL 89 *****************************************/ 90 int DeleteList(PLinkList L, int nPos, ElemType *val); 91 92 /**************************************** 93 Purpose : 返回线性表中第一个与e相等的数据元素的位序 94 Input : L -- 线性表指针 95 val -- 数据 96 compare -- 比较函数的函数指针 97 Return : 索引值,如果没有找到则返回-1 98 *****************************************/ 99 int LocateElem(PLinkList L, ElemType *val, Compare compare); 100 101 102 /**************************************** 103 Purpose : 遍历输出线性表中每个元素 104 Input : L -- 线性表指针 105 visit -- 遍历函数指针 106 Return : None 107 *****************************************/ 108 void TraverseList(PLinkList L, Visit visit); 109 110 /**************************************** 111 Purpose : 更新第nPos个位置元素 112 Input : L -- 线性表指针 113 nPos -- 元素的位置 [1, ListLength[L]] 114 data -- 要更新的元素 115 Return : 0 --OK 116 -1 --FAIL 117 *****************************************/ 118 int UpdateList(PLinkList L, int nPos, ElemType* val); 119 120 121 /**************************************** 122 Purpose : 对线性表进行排序 123 Input : L -- 线性表指针 124 compare -- 比较函数 125 Return : 0 --OK 126 -1 --FAIL 127 *****************************************/ 128 int SortList(PLinkList L, Compare compare); 129 130 /**************************************** 131 Purpose : 对线性表进行逆置 132 Input : L -- 线性表指针 133 compare -- 比较函数 134 Return : 0 --OK 135 -1 --FAIL 136 *****************************************/ 137 int ReverseList(PLinkList L);
LinkList.c
1 #include "LinkList.h" 2 3 4 /**************************************** 5 Purpose : 初始化线性表 6 Input : L -- 线性表指针 7 Return : 0 --OK 8 -1 --FAIL 9 *****************************************/ 10 int InitList(PLinkList L) 11 { 12 //带头结点的单链表 13 *L = (LinkList)malloc(sizeof(LNode)); 14 if(!*L) 15 { 16 return -1; 17 } 18 (*L)->next = NULL; 19 return 0; 20 } 21 22 /**************************************** 23 Purpose : 清空链表 24 Input : L -- 线性表指针 25 Return : None 26 *****************************************/ 27 void ClearList(PLinkList L) 28 { 29 LinkList p = *L; 30 while((*L)->next) 31 { 32 p=p->next; 33 free(*L); 34 *L = p; 35 } 36 (*L)->next = NULL; 37 } 38 39 /**************************************** 40 Purpose : 线性表长度 41 Input : L -- 线性表指针 42 Return : 线性表长度 如果是-1,则表示出错 43 *****************************************/ 44 int ListLength(PLinkList L) 45 { 46 LinkList p = NULL; 47 int nLen = 0; 48 if(*L == NULL) 49 { 50 return -1; 51 } 52 p = (*L)->next; 53 while(p) 54 { 55 p = p->next; 56 nLen++; 57 } 58 return nLen; 59 } 60 61 /**************************************** 62 Purpose : 取链表中第nPos个元素 63 Input : L -- 线性表指针 64 nPos -- 位置 65 val -- 要取到的元素 66 Return : 0 --OK 67 -1 --FAIL 68 *****************************************/ 69 int GetElem(PLinkList L, int nPos, ElemType *val) 70 { 71 LinkList p = *L; 72 int i = 0; 73 if(nPos > ListLength(L) || nPos < 0) 74 { 75 return -1; 76 } 77 while(i < nPos && p) 78 { 79 p = p->next; 80 i++; 81 } 82 memcpy(val, &p->data, sizeof(ElemType)); 83 return 0; 84 } 85 86 /**************************************** 87 Purpose : 在线性表中第nPos个位置插入新元素 88 Input : L -- 线性表指针 89 nPos -- 位置 [1,ListLength(L)+1] 90 val -- 要插入的元素 91 Return : 0 --OK 92 -1 --FAIL 93 *****************************************/ 94 int InsertList(PLinkList L, int nPos, ElemType *val) 95 { 96 LinkList p = *L; 97 LinkList q = NULL; 98 int i = 0; 99 int nLen = ListLength(L); 100 if(nPos < 1|| nPos > nLen+1) 101 { 102 return -1; 103 } 104 q = (LinkList)malloc(sizeof(LNode)); 105 if(q == NULL) 106 { 107 return -1; 108 } 109 while(i < nPos - 1) 110 { 111 p = p->next; 112 i++; 113 } 114 115 memcpy(&q->data, val, sizeof(ElemType)); 116 q->next = p->next; 117 p->next = q; 118 return 0; 119 } 120 121 /**************************************** 122 Purpose : 在线性表中第nPos个位置删除元素 123 Input : L -- 线性表指针 124 nPos -- 位置[1,ListLength(L)] 125 val -- 数据 126 Return : 0 --OK 127 -1 --FAIL 128 *****************************************/ 129 int DeleteList(PLinkList L, int nPos, ElemType *val) 130 { 131 LinkList p = *L; 132 LinkList q = NULL; 133 int i; 134 if(nPos < 1 || nPos > ListLength(L)) 135 { 136 return -1; 137 } 138 while(i < nPos -1) 139 { 140 p = p->next; 141 i++; 142 } 143 q = p->next; 144 p->next = q->next; 145 memcpy(val, &q->data, sizeof(ElemType)); 146 free(q); 147 q = NULL; 148 return 0; 149 } 150 151 152 /**************************************** 153 Purpose : 返回线性表中第一个与e相等的数据元素的位序 154 Input : L -- 线性表指针 155 val -- 数据 156 compare -- 比较函数的函数指针 157 Return : 索引值,如果没有找到则返回-1 158 *****************************************/ 159 int LocateElem(LinkList *L, ElemType *val, Compare compare) 160 { 161 LinkList p = NULL; 162 int i = 1; 163 if(*L == NULL) 164 { 165 return -1; 166 } 167 p = (*L)->next; 168 while(p && compare(val, &p->data) != 0) 169 { 170 p = p->next; 171 i++; 172 } 173 if(p == NULL) 174 { 175 return -1; 176 } 177 return i; 178 } 179 180 181 /**************************************** 182 Purpose : 遍历输出线性表中每个元素 183 Input : L -- 线性表指针 184 visit -- 遍历函数指针 185 Return : None 186 *****************************************/ 187 void TraverseList(PLinkList L, Visit visit) 188 { 189 LinkList p = NULL; 190 if(*L != NULL) 191 { 192 p = (*L)->next; 193 while(p != NULL) 194 { 195 visit(&p->data); 196 p = p->next; 197 } 198 } 199 } 200 201 /**************************************** 202 Purpose : 更新第nPos个位置元素 203 Input : L -- 线性表指针 204 nPos -- 元素的位置 [1, ListLength[L]] 205 data -- 要更新的元素 206 Return : 0 --OK 207 -1 --FAIL 208 *****************************************/ 209 int UpdateList(PLinkList L, int nPos, ElemType* val) 210 { 211 int i = 0; 212 LinkList p = NULL; 213 if(nPos < 1 && nPos > ListLength(L)) 214 { 215 return -1; 216 } 217 p = *L; 218 while(i < nPos) 219 { 220 p = p->next; 221 i++; 222 } 223 224 memcpy(&p->data, val, sizeof(ElemType)); 225 return 0; 226 } 227 228 229 230 /**************************************** 231 Purpose : 对线性表进行排序 232 Input : L -- 线性表指针 233 compare -- 比较函数 234 Return : 0 --OK 235 -1 --FAIL 236 *****************************************/ 237 int SortList(PLinkList L, Compare compare) 238 { 239 LinkList p = NULL; 240 LinkList q = NULL; 241 ElemType tmp; 242 if(*L == NULL) 243 { 244 return -1; 245 } 246 for(p = (*L)->next;p!=NULL;p=p->next) 247 { 248 for(q=p->next;q!=NULL;q=q->next) 249 { 250 if(compare(&q->data, &p->data) < 0) 251 { 252 memcpy(&tmp, &q->data, sizeof(ElemType)); 253 memcpy(&q->data, &p->data, sizeof(ElemType)); 254 memcpy(&p->data, &tmp, sizeof(ElemType)); 255 } 256 } 257 } 258 return 0; 259 } 260 261 /**************************************** 262 Purpose : 对线性表进行逆置 263 Input : L -- 线性表指针 264 compare -- 比较函数 265 Return : 0 --OK 266 -1 --FAIL 267 *****************************************/ 268 int ReverseList(PLinkList L) 269 { 270 LinkList p = NULL; 271 LinkList q = NULL; 272 LinkList s = NULL; 273 if(*L == NULL) 274 { 275 return -1; 276 } 277 p = (*L)->next; 278 if(p == NULL) 279 { 280 //没有数据则返回正确 281 return 0; 282 } 283 q = p->next; 284 while(q->next != NULL) 285 { 286 s = q->next; 287 q->next = p; 288 p = q; 289 q = s; 290 } 291 q->next = p; //最后一个节点的next调整下 292 (*L)->next->next = NULL; //保留头结点 293 (*L)->next = q; 294 return 0; 295 }
testmain.c
1 #include <stdio.h> 2 #include "LinkList.h" 3 4 void visit(ElemType *val) 5 { 6 printf("%3d ", *val); 7 } 8 int compare(ElemType* e1, ElemType* e2) 9 { 10 return *e1 - *e2; 11 } 12 int main(int argc, char* argv[]) 13 { 14 LinkList L; 15 int i; 16 ElemType val; 17 printf("初始化线性表\n"); 18 if(InitList(&L)) 19 { 20 printf("初始化线性表失败\n"); 21 return -1; 22 } 23 printf("插入数据1\n"); 24 val = 3; 25 if(InsertList(&L, 1, &val)) 26 { 27 printf("插入线性表数据失败\n"); 28 } 29 printf("插入数据2\n"); 30 val = 200; 31 if(InsertList(&L, 1, &val)) 32 { 33 printf("插入线性表数据失败\n"); 34 } 35 val = -1; 36 if(InsertList(&L, 1, &val)) 37 { 38 printf("插入线性表数据失败\n"); 39 } 40 for(i=0;i<8;i++) 41 { 42 val = i; 43 if(InsertList(&L, 1, &val)) 44 { 45 printf("插入线性表数据失败\n"); 46 } 47 } 48 TraverseList(&L, visit); 49 /*val = 555; 50 if(InsertList(&L, ListLength(&L), &val)) 51 { 52 printf("插入线性表数据失败\n"); 53 } 54 TraverseList(&L, visit); 55 printf("排序数据\n"); 56 SortList(&L, compare); 57 TraverseList(&L, visit); 58 printf("获取数据\n"); 59 if(GetElem(&L, 1, &val)) 60 { 61 printf("获取数据失败\n"); 62 } 63 visit(&val);*/ 64 /*int nLen = ListLength(&L); 65 printf("线性表长度[%d]\n", nLen); 66 printf("删除数据\n"); 67 if(DeleteList(&L, nLen, &val)) 68 { 69 printf("删除数据失败\n"); 70 } 71 TraverseList(&L, visit); 72 printf("删除的数据为\n"); 73 visit(&val); 74 printf("更新数据\n"); 75 val = 1000; 76 if(UpdateList(&L, 2, &val)) 77 { 78 printf("更新数据失败\n"); 79 } 80 TraverseList(&L, visit); 81 82 val = 555; 83 int nIndex = LocateElem(&L, &val, compare); 84 printf("定位数据位置为[%d]\n", nIndex); 85 */ 86 printf("\n逆置链表\n"); 87 if(ReverseList(&L)) 88 { 89 printf("逆置失败\n"); 90 } 91 TraverseList(&L, visit); 92 printf("\n"); 93 ClearList(&L); 94 return 0; 95 }