C语言实现单链表,并完成链表常用API函数:
1.链表增、删、改、查。
2.打印链表、反转打印、打印环形链表。
3.链表排序、链表冒泡排序、链表快速排序。
4.求链表节点个数(普通方法、递归方法)。
5.链表反转(普通方法、递归方法)。
6.链表合并。
7.获取链表中间节点。
8.判断链表是否有环。
LinkList.h :
1 #include2 #include 3 4 struct LinkNode 5 { 6 int data; 7 struct LinkNode *pNext; 8 }; 9 10 typedef struct LinkNode Node; //简化类型 11 12 void init(Node *phead); //初始化 13 Node *addBack(Node *phead, int data); //尾插法:尾部添加节点 14 void addHead(Node *phead, int data); //头插法:头部添加节点 15 16 void ShowAll(Node *phead); //显示链表 17 void revShowAll(Node *phead); //反转显示链表 18 void ShowCircleLink(Node *phead); //显示环形链表 19 20 Node *searchFirst(Node *phead, int findData); //查找 21 22 Node *changeFirst(Node *phead, int findData, int newData); //修改 23 24 Node *delFirst(Node *phead, int delData); //删除 25 26 Node *insertFirst(Node *phead, int insertData,int newData); //插入 27 28 void bubbleSort(Node *phead); //冒泡排序 29 30 void quickSort(Node *pbegin, Node *pback); //快速排序法:(双冒泡) 31 Node *fen(Node *pbegin, Node *pback); //分段 32 33 int getNum1(Node *phead); //求链表节点个数 34 int getNum2(Node *phead); //求链表节点个数(递归) 35 36 Node *revList1(Node *phead); //链表反转(普通方法) 37 Node *revList2(Node *phead); //链表反转(递归方法) 38 39 //将链表phead1和phead2合并到phead3,并返回链表phead3 40 Node *mergeList(Node *phead3, Node *phead1, Node *phead2); //链表合并 41 42 Node *getMid(Node *phead); //获取链表的中间节点 43 44 int judgeCircle(Node *phead); //判断链表是否有环
LinkList.c :
1 #include "LinkList.h" 2 3 //初始化 4 void init(Node *phead) 5 { 6 phead->pNext = NULL; 7 phead->data = 0; 8 } 9 10 //显示链表 11 void ShowAll(Node *phead) 12 { 13 if (phead == NULL) 14 return; 15 else 16 { 17 printf("%4d", phead->data); 18 //printf("%d,%p,%p\n", phead->data, phead, phead->pNext); 19 ShowAll(phead->pNext); //跳到下一个节点 20 21 } 22 } 23 24 //反转显示链表 25 void revShowAll(Node *phead) 26 { 27 if (phead == NULL) 28 return; 29 else 30 { 31 printf("%d,%p,%p\n", phead->data, phead, phead->pNext); 32 ShowAll(phead->pNext); //跳到下一个节点 33 34 } 35 } 36 37 //显示环形链表 38 void ShowCircleLink(Node *phead) 39 { 40 if (phead == NULL) 41 return; 42 else 43 { 44 Node *p = phead; 45 for (; p->pNext != phead; p = p->pNext) 46 printf("%4d", p->data); 47 48 printf("%4d", p->data); //还需要再打印最后一个元素 49 50 } 51 } 52 53 //尾插法:尾部添加节点 (改变了头指针,改变一个指针,要么二级指针,要么用返回值给指针赋值,这里采用返回值) 54 Node *addBack(Node *phead, int data) 55 { 56 Node *pnew = malloc(sizeof(Node)); //构建新的节点 57 pnew->data = data; //新节点赋值 58 pnew->pNext = NULL; 59 60 if (phead == NULL) //phead为空,直接连接 61 phead = pnew; 62 else 63 { 64 Node *ptemp = phead; //备份一下头指针 65 while (ptemp->pNext != NULL) 66 { 67 ptemp = ptemp -> pNext; //循环前进 68 } 69 ptemp->pNext = pnew; //链接 70 } 71 72 return phead; 73 } 74 75 //头插法:头部添加节点 (采用二级指针的方法) 76 void addHead(Node **pphead, int data) 77 { 78 Node *pnew = malloc(sizeof(Node)); //构建新的节点 79 pnew->data = data; //新节点赋值 80 pnew->pNext = NULL; 81 82 if(*pphead==NULL) 83 pphead = pnew; 84 else 85 { 86 pnew->pNext = *pphead; 87 *pphead = pnew; 88 } 89 } 90 91 //查找 92 Node *searchFirst(Node *phead, int findData) 93 { 94 for (Node *p = phead; p != NULL; p = p->pNext) 95 { 96 if (p->data == findData) 97 { 98 return p; //返回找到的指针位置 99 } 100 } 101 102 return NULL; 103 } 104 105 //修改 106 Node *changeFirst(Node *phead, int findData, int newData) 107 { 108 for (Node *p = phead; p != NULL; p = p->pNext) 109 { 110 if (p->data == findData) 111 { 112 p->data = newData; 113 return p; //返回找到的指针位置 114 } 115 } 116 117 return NULL; 118 } 119 120 //删除 121 Node *delFirst(Node *phead, int delData) 122 { 123 Node *p1=NULL, *p2=NULL; //此时需要双指针 124 p1 = phead; //保存头结点 125 126 while (p1 != NULL) 127 { 128 if (p1->data != delData) 129 { 130 p2 = p1; //p2保存的是p1的上一个位置 131 p1 = p1->pNext; 132 } 133 else 134 break; 135 } 136 137 if (p1 != phead) 138 { 139 p2->pNext = p1->pNext; //跳过p1 140 free(p1); //删除p1 141 } 142 else 143 { 144 phead = phead->pNext; 145 free(p1); //头部删除 146 } 147 148 return phead; 149 } 150 151 //插入 152 Node *insertFirst(Node *phead, int insertData, int newData) 153 { 154 Node *p1 = NULL, *p2 = NULL; //此时需要双指针 155 p1 = phead; //保存头结点 156 157 while (p1 != NULL) 158 { 159 if (p1->data != insertData) 160 { 161 p2 = p1; //p2保存的是p1的上一个位置 162 p1 = p1->pNext; //向前移动 163 } 164 else 165 break; 166 } 167 168 Node *pnew = malloc(sizeof(Node)); //构建新的节点 169 pnew->data = newData; //新节点赋值 170 pnew->pNext = NULL; 171 172 if (phead == p1) 173 { 174 pnew->pNext = phead; //保存头结点 175 phead = pnew; //头部插入 176 } 177 else 178 { 179 pnew->pNext = p1; 180 p2->pNext = pnew; //插入 181 } 182 183 return phead; 184 } 185 186 //冒泡排序 187 void bubbleSort(Node *phead) 188 { 189 //数组可以随机访问任何一个元素,可以规避一些比较 190 //链表找到N个元素,必须先遍历N-1个元素 191 for (Node *p1 = phead; p1 != NULL; p1 = p1->pNext) 192 { 193 for (Node *p2 = phead; p2 != NULL; p2 = p2->pNext) 194 { 195 if (p1->data < p2->data) 196 { 197 int temp; 198 temp = p1->data; 199 p1->data = p2->data; 200 p2->data = temp; 201 } 202 } 203 } 204 } 205 206 Node *fen(Node *pbegin, Node *pback) 207 { 208 int key = pbegin->data; //以第一个数据为分段 209 210 Node *p = pbegin; //第一个节点 211 Node *q = pbegin->pNext; //第二个节点 212 213 while (q != pback) 214 { 215 if (q->data < key) 216 { 217 p = p->pNext; //循环下一个节点 218 219 int temp = p->data; //交换 220 p->data = q->data; 221 q->data = temp; 222 } 223 q = q->pNext; //循环第二个指针 224 225 printf("\n枢轴为:(%d)", key); 226 printf("\n此时数:"); 227 ShowAll(pbegin); 228 229 } 230 231 int temp = p->data; //交换 232 p->data = pbegin->data; 233 pbegin->data = temp; 234 235 printf("\n\n交换值:"); 236 ShowAll(pbegin); 237 printf("\n-----------------------------------------------"); 238 239 return p; 240 } 241 242 //快速排序法:(双冒泡) 243 void quickSort(Node *pbegin,Node *pback) 244 { 245 if (pbegin != pback) 246 { 247 Node *pfen = fen(pbegin, pback); //取中间点,分成两段分别再进行快排 248 249 quickSort(pbegin, pfen); //前半段快排 250 quickSort(pfen->pNext, pback); //后半段快排 251 } 252 } 253 254 //求链表节点个数(普通方法) 255 int getNum1(Node *phead) 256 { 257 int i = 0; 258 for (; phead != NULL; phead = phead->pNext) 259 { 260 i++; 261 } 262 return i; 263 } 264 265 //求链表节点个数(递归) 266 int getNum2(Node *phead) 267 { 268 if (phead == NULL) 269 return 0; 270 else 271 return 1 + getNum2(phead->pNext); 272 } 273 274 //链表反转(普通方法) 275 Node *revList1(Node *phead) 276 { 277 if (phead == NULL || phead->pNext == NULL) 278 return phead; 279 else 280 { 281 Node *pre = NULL; 282 Node *pcur = NULL; 283 Node *pnext = NULL; 284 285 pre = phead; 286 pcur = phead->pNext; 287 while (pcur != NULL) 288 { 289 pnext = pcur->pNext; //备份下一个节点 290 pcur->pNext = pre; //第一个节点指向NULL,此时pre指向NULL(指针反转) 291 292 pre = pcur; //前进 293 pcur = pnext; //轮替前进 294 } 295 296 phead->pNext = NULL; //注意尾节点置空 297 phead = pre; 298 } 299 300 return phead; 301 } 302 303 //链表反转(递归方法) 304 Node *revList2(Node *phead) 305 { 306 if (phead == NULL || phead->pNext == NULL) 307 return phead; 308 else 309 { 310 Node *pnext = phead->pNext; //顺序 311 312 Node *Head = revList2(pnext); //轮询所有的节点,递归调用 313 314 pnext->pNext = phead; 315 316 phead->pNext = NULL; //逆序 317 318 return Head; 319 } 320 } 321 322 //链表合并 323 Node *mergeList(Node *phead3, Node *phead1, Node *phead2) 324 { 325 Node *pcur1 = phead1; 326 Node *pcur2 = phead2; 327 328 while (pcur1 != NULL || pcur2 != NULL) 329 { 330 if (pcur1 != NULL && pcur2 != NULL) 331 { 332 if (pcur1->data < pcur2->data) 333 { 334 phead3 = addBack(phead3, pcur1->data); 335 pcur1 = pcur1->pNext; 336 } 337 else 338 { 339 phead3 = addBack(phead3, pcur2->data); 340 pcur2 = pcur2->pNext; 341 } 342 } 343 else 344 { 345 while (pcur1 != NULL) 346 { 347 phead3 = addBack(phead3, pcur1->data); 348 pcur1 = pcur1->pNext; 349 } 350 while (pcur2 != NULL) 351 { 352 phead3 = addBack(phead3, pcur2->data); 353 pcur2 = pcur2->pNext; 354 } 355 356 break; 357 } 358 } 359 360 return phead3; 361 } 362 363 //获取链表的中间节点 364 Node *getMid(Node *phead) 365 { 366 if (phead == NULL || phead->pNext == NULL) 367 return phead; 368 else 369 { 370 Node *p1 = phead; //一次前进一步 371 Node *p2 = phead; //一次前进两步 372 373 while (p2->pNext != NULL) //注意循环条件,而不是p2 != NULL 374 { 375 p1 = p1->pNext; 376 p2 = p2->pNext; 377 if (p2->pNext != NULL) 378 p2 = p2->pNext; 379 } 380 381 return p1; 382 } 383 } 384 385 //判断链表是否有环 386 int judgeCircle(Node *phead) 387 { 388 int flag = 0; 389 for (Node *p1 = phead, *p2 = phead; p1 != NULL && p2 != NULL; p1 = p1->pNext, p2 = p2->pNext) //死循环 390 { 391 if(p2->pNext!=NULL) //p2一次前进两步,而p1一次前进一步 392 p2 = p2->pNext; 393 394 if (p1 == p2) 395 { 396 flag == 1; //p1追上了p2,有环 397 break; 398 } 399 400 401 } 402 403 return flag; 404 }
main.c :
1 #include "LinkList.h" 2 3 void main() 4 { 5 Node *phead = NULL; 6 //init(phead); //初始化,头结点不分配内存,这里不能初始化头结点 7 8 phead = addBack(phead, 14); //尾插 9 phead = addBack(phead, 15); 10 phead = addBack(phead, 16); 11 phead = addBack(phead, 8); 12 phead = addBack(phead, 12); 13 phead = addBack(phead, 13); 14 15 //addHead(&phead, 9); //头插 16 //addHead(&phead, 22); 17 //addHead(&phead, 41); 18 //addHead(&phead, 18); 19 //ShowAll(phead); 20 21 //Node *pfind = searchFirst(phead, 13); 22 //pfind->data = 33; 23 //ShowAll(phead); 24 25 //Node *pchange = changeFirst(phead, 14,93); 26 //ShowAll(phead); 27 28 //ShowAll(phead); 29 //printf("\n\n"); 30 //phead = delFirst(phead, 24); 31 //ShowAll(phead); 32 33 //printf("\n\n"); 34 //insertFirst(phead, 11, 100); 35 //ShowAll(phead); 36 37 printf("排序前:"); 38 ShowAll(phead); 39 printf("\n\n"); 40 41 //bubbleSort(phead); 42 quickSort(phead, NULL); 43 44 printf("\n\n"); 45 printf("排序后:"); 46 ShowAll(phead); 47 printf("\n"); 48 49 printf("%d\n", getNum2(phead)); 50 51 phead = revList1(phead); 52 ShowAll(phead); 53 printf("\n"); 54 phead = revList2(phead); 55 ShowAll(phead); 56 printf("\n"); 57 58 Node *phead1 = NULL; 59 phead1 = addBack(phead1, 1); 60 phead1 = addBack(phead1, 3); 61 phead1 = addBack(phead1, 5); 62 phead1 = addBack(phead1, 7); 63 phead1 = addBack(phead1, 9); 64 65 Node *phead2 = NULL; 66 phead2 = addBack(phead2, 2); 67 phead2 = addBack(phead2, 4); 68 phead2 = addBack(phead2, 6); 69 phead2 = addBack(phead2, 8); 70 71 printf("\n\n\n"); 72 ShowAll(phead1); 73 printf("\n"); 74 ShowAll(phead2); 75 printf("\n"); 76 77 Node *phead3 = NULL; 78 phead3 = mergeList(phead3, phead1, phead2); 79 ShowAll(phead3); 80 printf("\n"); 81 82 Node *pmid = getMid(phead3); 83 printf("%d\n", pmid->data); 84 85 Node *phead4 = NULL; 86 phead4 = addBack(phead4, 1); 87 phead4 = addBack(phead4, 2); 88 phead4 = addBack(phead4, 3); 89 phead4 = addBack(phead4, 4); 90 phead4 = addBack(phead4, 5); 91 phead4 = addBack(phead4, 6); 92 phead4 = addBack(phead4, 7); 93 94 Node *p = phead4; 95 for (; p->pNext != NULL; p = p->pNext) 96 { 97 } 98 p->pNext = phead4; 99 100 ShowCircleLink(phead4); //打印环形链表 101 printf("\n"); 102 printf("%d\n", judgeCircle(phead4)); 103 104 system("pause"); 105 }