//VS2022 x86編譯器下已測驗通過
//C語言 鏈表的基本使用 -- 13個函式,初始化(頭插、尾插)、遍歷列印、獲取元素總個數、插入(按值前插/后插、按位置)、洗掉(按值、按位置)、逆置、清空、銷毀
//如果在CLion中使用,請將這三個檔案放在CMakeLists.txt的同級目錄下,在CMakeLists.txt中添加如下內容,生成程式后,在終端切換到對應的exe所在檔案夾,之后輸入程式名稱(.\Demo.exe) 即可開始運行,或者Run程式,之后在Run的視窗中,修改如下:Edit Run Configuration -- 勾選Run in external console,之后Rerun,也可以運行,測驗代碼輸入1,2,3,4,5,-1,即可得到Demo.c檔案中那些被注釋的鏈表結果,
include_directories(.) add_executable(Demo Demo.c linklist.c)
示例代碼:三個檔案,linklist.h、linklist.c 和Demo.c
linklist.h代碼:
1 #pragma once 2 3 #define _CRT_SECURE_NO_WARNINGS 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 //定義結點 9 struct LinkNode 10 { 11 int num; 12 struct LinkNode* next; 13 }; 14 15 //01.初始化鏈表:尾插法:可以使遍歷鏈表得出的資料和輸入的資料順序相同 16 struct LinkNode* initLinkListTail(); 17 18 //02.初始化鏈表:頭插法:可以使遍歷鏈表得出的資料和輸入的資料順序相反 19 struct LinkNode* initLinkListHead(); 20 21 //03.遍歷鏈表,并列印輸出 22 void foreach_LinkList(struct LinkNode* pHeader); 23 24 //04.獲取鏈表長度,獲取鏈表中元素個數 25 int getElementNums(struct LinkNode* pHeader); 26 27 //05.獲取鏈表中某位置對應的結點的值,假設頭結點為第0個結點,pos為鏈表中第pos個結點 28 int getValueByPos(struct LinkNode* pHeader, int pos); 29 30 //06.向鏈表插入新結點(根據結點值):到現存結點前面或末尾 31 void insert_LinkListByValueBefore(struct LinkNode* pHeader, int oldVal, int newVal); 32 33 //07.向鏈表插入新結點(根據結點值):到現存結點后面或末尾,尾插法 34 void insert_LinkListByValueAfter(struct LinkNode* pHeader, int oldVal, int newVal); 35 36 //08.向鏈表插入新節點(根據給定位置):位置需要為大于0的數 37 void insert_LinkListByPos(struct LinkNode* pHeader, int pos, int newVal); 38 39 //09.洗掉鏈表(根據給定結點值):洗掉鏈表中某個結點 40 void delete_LinkListByValue(struct LinkNode* pHeader, int delVal); 41 42 //10.洗掉鏈表(根據給定位置):洗掉鏈表中某個結點 43 void delete_LinkListByPos(struct LinkNode* pHeader, int pos); 44 45 //11.反轉鏈表:逆置 46 void reverse_LinkList(struct LinkNode* pHeader); 47 48 //12.清空鏈表(可以復用):清空各結點資料域,保留指標域,保留頭結點 49 void clear_LinkList(struct LinkNode* pHeader); 50 51 //13.銷毀鏈表:頭結點和之后所有結點全部洗掉,一個不留 52 void destroy_LinkList(struct LinkNode* pHeader);View Code
linklist.c代碼
1 #include "linklist.h" 2 3 4 5 //01.尾插法:初始化鏈表,函式回傳值是創建好的鏈表的頭結點 6 struct LinkNode* initLinkListTail() 7 { 8 struct LinkNode* pHeader = (struct LinkNode*)malloc(sizeof(struct LinkNode)); 9 if (pHeader == NULL) 10 { 11 return NULL; 12 } 13 14 pHeader->next = NULL; 15 struct LinkNode* pTail = pHeader; 16 int val = -1; 17 while (1) 18 { 19 printf("請初始化鏈表,輸入一個數字,并按Enter鍵,如果輸入-1則代表結束\n"); 20 scanf("%d", &val); 21 if (val == -1) 22 { 23 break; 24 } 25 struct LinkNode* newNode = (struct LinkNode*)malloc(sizeof(struct LinkNode)); 26 newNode->num = val; 27 newNode->next = NULL; 28 29 pTail->next = newNode; 30 pTail = newNode; 31 } 32 33 return pHeader; 34 } 35 36 37 //02.頭插法:初始化鏈表,函式回傳值是創建好的鏈表的頭結點 38 struct LinkNode* initLinkListHead() 39 { 40 struct LinkNode* pHeader = (struct LinkNode*)malloc(sizeof(struct LinkNode)); 41 if (pHeader == NULL) 42 { 43 return NULL; 44 } 45 46 pHeader->next = NULL; 47 //struct LinkNode* pTail = pHeader; 48 int val = -1; 49 while (1) 50 { 51 printf("請初始化鏈表,如果輸入-1代表結束\n"); 52 scanf("%d", &val); 53 if (val == -1) 54 { 55 break; 56 } 57 struct LinkNode* newNode = (struct LinkNode*)malloc(sizeof(struct LinkNode)); 58 newNode->num = val; 59 newNode->next = pHeader->next; 60 61 pHeader->next = newNode; 62 //pTail = newNode; 63 } 64 65 return pHeader; 66 } 67 68 69 //03.遍歷鏈表,并列印輸出 70 void foreach_LinkList(struct LinkNode* pHeader) 71 { 72 if (pHeader == NULL) 73 { 74 return; 75 } 76 struct LinkNode* pCurrent = pHeader->next; 77 int i = 0; 78 while (pCurrent != NULL) 79 { 80 printf("鏈表中第%d個結點的資料域的值為: %d\n", i + 1, pCurrent->num); 81 i++; 82 pCurrent = pCurrent->next; 83 } 84 } 85 86 87 //04.獲取鏈表長度,獲取鏈表中元素個數 88 int getElementNums(struct LinkNode* pHeader) 89 { 90 int nums = 0; 91 if (pHeader == NULL) 92 { 93 return 0; 94 } 95 struct LinkNode* pCurrent = pHeader->next; 96 97 while (pCurrent != NULL) 98 { 99 nums++; 100 pCurrent = pCurrent->next; 101 } 102 return nums; 103 } 104 105 106 //05.獲取鏈表中某位置對應的結點的值,假設頭結點為第0個結點,pos為鏈表中第pos個結點 107 int getValueByPos(struct LinkNode* pHeader, int pos) 108 { 109 struct LinkNode* tmpHeader = pHeader; 110 if (pHeader == NULL) 111 { 112 return -1; 113 } 114 115 int lens = getElementNums(pHeader); 116 if (pos <= 0) 117 { 118 printf("位置值不得為負數或0,請輸入正確的位置\n"); 119 return -1; 120 } 121 if (pos > lens) 122 { 123 printf("位置值不得大于元素中的個數值,現在鏈表中已有%d個元素,請輸入正確的位置\n", lens); 124 return -1; 125 } 126 127 int i = 0; 128 while (i < pos) 129 { 130 tmpHeader = tmpHeader->next; 131 i++; 132 } 133 int value = https://www.cnblogs.com/songteng0604/archive/2022/05/07/tmpHeader->num; 134 135 return value; 136 } 137 138 139 //06.向鏈表插入新結點(根據結點值):到現存結點前面或末尾,如果存在該0ldVal值,就創建新節點,賦值為newVal,并插入到oldVal結點前面,如果不存在,則創建一個新結點,并插入到現有鏈表的尾部,新節點成為鏈表中最后一個結點, 140 void insert_LinkListByValueBefore(struct LinkNode* pHeader, int oldVal, int newVal) 141 { 142 if (pHeader == NULL) 143 { 144 return; 145 } 146 147 //創建兩個臨時的節點 148 struct LinkNode* pPrve = pHeader; 149 struct LinkNode* pCurrent = pHeader->next; 150 151 while (pCurrent != NULL) 152 { 153 if (pCurrent->num == oldVal) 154 { 155 break; 156 } 157 //如果沒找到對應的位置,輔助指標向后移動 158 pPrve = pCurrent; 159 pCurrent = pCurrent->next; //如果沒找到oldVal,則pCurrent = pCurrent->next = NULL; 160 } 161 162 //創建新節點 163 struct LinkNode* newNode = malloc(sizeof(struct LinkNode)); 164 newNode->num = newVal; 165 newNode->next = NULL; 166 167 168 //建立關系 169 newNode->next = pCurrent; //如果沒找到,則pCurrent=NULL 170 pPrve->next = newNode; //將新節點掛在pPrve的后面,即如果找到就是oldVal前面的一個結點,如果沒找到就是鏈表最后一個結點, 171 172 } 173 174 175 //07.向鏈表插入新結點(根據結點值):到現存結點后面或末尾,如果存在該0ldVal值,就創建新節點,賦值為newVal,并插入到oldVal結點前面,如果不存在,則創建一個新結點,并插入到現有鏈表的尾部,新節點成為鏈表中最后一個結點, 176 void insert_LinkListByValueAfter(struct LinkNode* pHeader, int oldVal, int newVal) 177 { 178 if (pHeader == NULL) 179 { 180 return; 181 } 182 183 //創建兩個臨時的節點 184 struct LinkNode * pTail = pHeader; 185 struct LinkNode* pCurrent = pHeader->next; 186 int flag = 0; 187 188 while (pCurrent != NULL) 189 { 190 if (pCurrent->num == oldVal) 191 { 192 flag = 1; 193 break; 194 } 195 //如果沒找到對應的位置,輔助指標向后移動 196 pTail = pCurrent; 197 pCurrent = pCurrent->next; //如果沒找到oldVal,則pCurrent = pCurrent->next = NULL; 198 } 199 if (flag == 1) 200 { 201 struct LinkNode* newNode = malloc(sizeof(struct LinkNode)); 202 newNode->num = newVal; 203 newNode->next = pCurrent->next; 204 pCurrent->next = newNode; 205 } 206 else { 207 //printf("未找到,失敗\n"); 208 struct LinkNode* newNode = malloc(sizeof(struct LinkNode)); 209 newNode->num = newVal; 210 newNode->next = NULL; 211 212 //更改指標的指向 213 pTail->next = newNode; 214 //更新新的尾節點的指向 215 pTail = newNode; 216 } 217 } 218 219 220 //08.向鏈表插入新節點(根據給定位置):位置需要為大于0的數 221 void insert_LinkListByPos(struct LinkNode* pHeader, int pos, int newVal) 222 { 223 int num = getValueByPos(pHeader, pos); 224 225 //printf("此時:pos= %d, num = %d\n", pos, num); //此時pos等于i 226 if (num == -1) 227 { 228 printf("當前pos引數輸入錯誤,本次插入失敗\n"); 229 } 230 else { 231 insert_LinkListByValueBefore(pHeader, num, newVal); 232 } 233 } 234 235 236 //09.洗掉鏈表(根據給定結點值):洗掉鏈表中某個結點 237 void delete_LinkListByValue(struct LinkNode* pHeader, int delVal) 238 { 239 if (pHeader == NULL) 240 { 241 return; 242 } 243 244 //創建兩個輔助指標變數 245 struct LinkNode* pPrev = pHeader; 246 struct LinkNode* pCurrent = pHeader->next; 247 248 while (pCurrent != NULL) 249 { 250 if (pCurrent->num == delVal) 251 { 252 break; 253 } 254 //沒有找到資料,輔助指標向后移動 255 pPrev = pCurrent; 256 pCurrent = pCurrent->next; 257 } 258 259 if (pCurrent == NULL) //沒有找到用戶要洗掉的資料 260 { 261 return; 262 } 263 264 //更改指標的指向進行洗掉 265 pPrev->next = pCurrent->next; 266 267 //洗掉掉待洗掉的節點 268 free(pCurrent); 269 pCurrent = NULL; 270 } 271 272 273 //10.洗掉鏈表(根據給定位置):洗掉鏈表中某個結點 274 void delete_LinkListByPos(struct LinkNode* pHeader, int pos) 275 { 276 int num = getValueByPos(pHeader, pos); 277 if (num == -1) 278 { 279 printf("當前pos引數輸入錯誤,本次洗掉失敗\n"); 280 } 281 else { 282 delete_LinkListByValue(pHeader, num); 283 } 284 } 285 286 287 //11.反轉鏈表:逆置 -- 我寫的 288 void reverse_LinkList1(struct LinkNode* pHeader) 289 { 290 if (pHeader == NULL) 291 { 292 return; 293 } 294 295 struct LinkNode* pCurrent = pHeader->next; 296 297 if (pCurrent == NULL) 298 { 299 printf("空鏈表,逆置失敗,\n"); 300 return; 301 } 302 303 pHeader->next = NULL; 304 305 int tmpValue = https://www.cnblogs.com/songteng0604/archive/2022/05/07/pCurrent->next; 306 while (pCurrent != NULL) 307 { 308 insert_LinkListByValueBefore(pHeader, tmpValue, pCurrent->num); 309 tmpValue = https://www.cnblogs.com/songteng0604/archive/2022/05/07/pCurrent->num; 310 pCurrent = pCurrent->next; 311 } 312 //洗掉掉待洗掉的節點 313 free(pCurrent); 314 pCurrent = NULL; 315 } 316 317 //11-1.反轉鏈表:逆置 -- 課程老師給定 318 void reverse_LinkList(struct LinkNode* pHeader) 319 { 320 if (pHeader == NULL) 321 { 322 return; 323 } 324 325 struct LinkNode* pCurrent = pHeader->next; 326 struct LinkNode* pPrev = NULL; 327 struct LinkNode* pNext = NULL; 328 329 while (pCurrent != NULL) 330 { 331 pNext = pCurrent->next; 332 //更改指標指向 333 pCurrent->next = pPrev; 334 335 //移動輔助指標 336 pPrev = pCurrent; 337 pCurrent = pNext; 338 } 339 340 //更新頭結點 341 pHeader->next = pPrev; 342 343 } 344 345 //12.清空鏈表(可以復用):清空各結點資料域,保留指標域,保留頭結點 346 void clear_LinkList(struct LinkNode* pHeader) 347 { 348 if (pHeader == NULL) 349 { 350 return; 351 } 352 353 struct LinkNode* pCurrent = pHeader->next; 354 355 while (pCurrent != NULL) 356 { 357 //先保存住下一個節點的位置 358 struct LinkNode* nextNode = pCurrent->next; 359 360 free(pCurrent); 361 362 pCurrent = nextNode; 363 } 364 365 pHeader->next = NULL; 366 } 367 368 369 //13.銷毀鏈表:頭結點和之后所有結點全部洗掉,一個不留 370 void destroy_LinkList(struct LinkNode* pHeader) 371 { 372 if (pHeader == NULL) 373 { 374 return; 375 } 376 377 //先清空鏈表 378 clear_LinkList(pHeader); 379 380 //再釋放頭節點 381 382 free(pHeader); 383 pHeader = NULL; 384 }View Code
Demo.c代碼
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include "linklist.h" 6 7 //如果是學習之用,可以將注釋分布取消,以觀察輸出的結果,如果是用例的呼叫需要,可以直接將注釋全部洗掉 8 void test01() 9 { 10 //初始化 11 struct LinkNode* pHeader = initLinkListTail(); //假設輸入1,2,3,4,5,-1 ,尾插法 12 //struct LinkNode* pHeader = initLinkListHead(); 13 14 //遍歷 15 foreach_LinkList(pHeader); //尾插法:1,2,3,4,5 ;頭插法:5,4,3,2,1 16 17 //獲取元素個數 18 int lens = getElementNums(pHeader); 19 printf("lens = %d\n", lens); //lens = 5 20 printf("間隔行:1*********************************************\n\n"); 21 22 //向鏈表插入新結點(根據結點值):到現存結點前面或末尾 23 //insert_LinkListByValueBefore(pHeader,3, 8); //在鏈表中如果找到對應給定值的結點,就在該節點的前面插入 24 //foreach_LinkList(pHeader);//1,2,8,3,4,5 25 //printf("間隔行:2*********************************************\n\n"); 26 //insert_LinkListByValueBefore(pHeader, 6, 9); //在鏈表中如果沒有找到給定值的結點,就在最后插入 27 //foreach_LinkList(pHeader);//1,2,8,3,4,5,9 28 //printf("間隔行:3*********************************************\n\n"); 29 30 //向鏈表插入新結點(根據結點值):到現存結點后面或末尾,尾插法 31 //insert_LinkListByValueAfter(pHeader, 3, 10);//在鏈表中如果找到給定值的結點,就在該結點的后面插入 32 //foreach_LinkList(pHeader);//1,2,8,3,10,4,5,9 33 //printf("間隔行:4*********************************************\n\n"); 34 //insert_LinkListByValueAfter(pHeader, 6, 11);//在鏈表中如果沒有找到給定值的結點,就在最后插入 35 //foreach_LinkList(pHeader);//1,2,8,3,10,4,5,9,11 36 //printf("間隔行:5*********************************************\n\n"); 37 38 //向鏈表插入新節點(根據給定位置):位置需要為大于0的數 39 //insert_LinkListByPos(pHeader, 0,12); 40 insert_LinkListByPos(pHeader, 3, 12); 41 //insert_LinkListByPos(pHeader, 5, 12); 42 //insert_LinkListByPos(pHeader, 6, 12); 43 foreach_LinkList(pHeader); //1,2,12,3,4,5 44 printf("間隔行:6*********************************************\n\n"); 45 46 //洗掉鏈表(根據給定結點值):洗掉鏈表中某個結點 47 delete_LinkListByValue(pHeader, 12); 48 foreach_LinkList(pHeader); //1,2,3,4,5 49 printf("間隔行:7*********************************************\n\n"); 50 //delete_LinkListByValue(pHeader, 4); 51 //foreach_LinkList(pHeader); //1,2,12,3,4,5 52 //printf("間隔行:8*********************************************\n\n"); 53 //delete_LinkListByValue(pHeader, 8); //鏈表中并沒有8,不做洗掉 54 //foreach_LinkList(pHeader); //1,2,12,3,4,5 55 //printf("間隔行:9********************************************\n\n"); 56 57 //洗掉鏈表(根據給定位置):洗掉鏈表中某個結點 58 delete_LinkListByPos(pHeader, 3); 59 foreach_LinkList(pHeader); //1,2,4,5 60 lens = getElementNums(pHeader); 61 printf("lens = %d\n", lens); //lens = 4 62 delete_LinkListByPos(pHeader, lens); 63 foreach_LinkList(pHeader); //1,2,4 64 lens = getElementNums(pHeader); 65 printf("lens = %d\n", lens); //lens = 3 66 printf("間隔行:10*********************************************\n\n"); 67 68 69 //反轉鏈表:逆置 70 reverse_LinkList(pHeader); 71 foreach_LinkList(pHeader); //4,2,1 72 lens = getElementNums(pHeader); 73 printf("lens = %d\n", lens); //lens = 3 74 printf("間隔行:11*********************************************\n\n"); 75 76 //清空鏈表(可以復用):清空各結點資料域,保留指標域,保留頭結點 77 clear_LinkList(pHeader); 78 foreach_LinkList(pHeader); //不列印 79 lens = getElementNums(pHeader); 80 printf("lens = %d\n", lens); //lens = 0 81 printf("間隔行:12*********************************************\n\n"); 82 83 //銷毀鏈表:頭結點和之后所有結點全部洗掉,一個不留 84 destroy_LinkList(pHeader); 85 pHeader = NULL; 86 printf("間隔行:13*********************************************\n\n"); 87 88 89 } 90 91 int main() 92 { 93 test01(); 94 95 printf("\n"); 96 system("pause"); 97 return 0; 98 }View Code
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/469924.html
標籤:其他
上一篇:饅頭的1day漏洞巡艦系統
