1 #define _CRT_SECURE_NO_WARNINGS 2 #include3 #include 4 5 6 typedef struct Node 7 { 8 int data; 9 struct Node *next; 10 }SLIST; 11 12 13 //创建链表 14 SLIST *Slist_create() 15 { 16 SLIST *pHead, *pM, *pCur; //申请链表的辅助指针变量 17 int data; //数据域的接收 18 19 //创建头节点并初始化 20 pHead = (SLIST *)malloc(sizeof(SLIST)); 21 if (NULL == pHead) 22 return NULL; 23 pHead->data = 0; 24 pHead->next = NULL; 25 26 //提示输入内容 27 printf("plz input the data \n"); 28 scanf("%d", &data); 29 30 //对当前结点进行定位 31 pCur = pHead; 32 33 //循环创建业务节点 34 while (data != -1) 35 { 36 //创建业务节点实际操作、然后初始化 37 pM = ((SLIST *)malloc(sizeof(SLIST))); 38 if (NULL == pM) 39 return NULL; 40 pM->data = data; 41 pM->next = NULL; 42 43 //业务节点入链表 44 pCur->next = pM; 45 46 //当前节点下移 47 pCur = pM; 48 49 //提示输入内容 50 printf("plz input the data \n"); 51 scanf("%d", &data); 52 53 } 54 55 return pHead; 56 } 57 58 59 //打印链表 60 int Slist_printf(SLIST *pHead) //形参接收头节点地址 61 { 62 SLIST *tap = NULL; //创建临时指针变量 63 if (NULL == pHead) 64 return -1; 65 67 //临时指针变量初始化 :第一个节点 68 tap = pHead->next; 69 70 printf("\nSTART\n"); 71 while (tap) 72 { 73 //打印当前结点数据域的内容 74 printf("%d ", tap->data); 75 76 //临时指针变量下移 77 tap = tap->next; 78 } 79 printf("END\n"); 80 return 0; 81 } 82 83 //在链表中某一位置插入元素 84 int Slist_NodeInsert(SLIST *pHead, int x, int y) 85 { 86 //创建辅助指针变量 87 SLIST *pPre, *pCur, *pM; 88 89 //前驱结点初始化 90 pPre = pHead; 91 //当前结点初始化 92 pCur = pHead->next; 93 //创建插入节点 94 pM = (SLIST *)malloc(sizeof(SLIST)); 95 //插入节点初始化 96 pM->next = NULL; 97 //数据域为要插入的值 98 pM->data = y; 99 //遍历链表100 while (pCur)101 {102 //判断元素节点,如果是跳出循环103 if (pCur->data == x)104 break;105 //指针下移106 pPre = pCur;107 pCur = pCur->next;108 109 }110 //插入节点入链表:分为两种情况,①找到要插入的节点插入在当前位置②未找到要插入的节点,插入在链表尾部111 pM->next = pPre->next;112 pPre->next = pM;113 return 0;114 }115 116 //删除链表节点117 int Slist_NodeDel(SLIST *pHead, int y)118 {119 //创建辅助指针变量120 SLIST *pPre, *pCur;121 //指针变量初始化122 pPre = pHead;123 pCur = pHead->next;124 125 //遍历链表126 while (pCur)127 {128 //判断是否找到要删除的链表节点;如果是则跳出循环129 if (pCur->data == y)130 break;131 132 //指针下移133 pPre = pCur;134 pCur = pCur->next;135 }136 //判断是否找到要删除的链表节点:未找到137 if (pCur == NULL)138 {139 printf("未找到要删除的节点\n");140 return -1;141 }142 //找到要删除的链表节点143 pPre->next = pCur->next;144 //这段判断语句的作用是:判断链表是否存在145 if (pPre == NULL)146 free(pCur); //释放当前节点内存(即要删除节点的内存)147 return 0;148 }149 150 //链表逆置151 int Slist_Reverse(SLIST *pHead)152 {153 //创建指针变量154 SLIST *pPre, *pCur, *tap;155 //判断是否需要逆置:(当链表元素>=2时才可以逆置)156 if (pHead == NULL || pHead->next == NULL || pHead->next->next == NULL)157 return -1;158 //初始化指针变量159 pPre = pHead->next;160 pCur = pHead->next->next;161 //遍历链表162 while (pCur)163 {164 //缓存当前结点的指针域165 tap = pCur->next;166 //对当前结点的指针域重新赋值为前驱结点; 即逆置167 pCur->next = pPre; //(这里有做错:写成pCur->next = pPre-next)168 //指针下移169 pPre = pCur;170 pCur = tap;171 }172 173 //对头节点和第一个元素的指针域进行处理174 pHead->next->next = NULL;175 pHead->next = pPre;176 177 return 0;178 }179 180 //销毁链表181 int Slist_Destory(SLIST *pHead)182 {183 //创建辅助指针变量184 SLIST *tap;185 186 //判断链表是否存在187 if (pHead == NULL)188 return -1;189 //遍历链表190 while (pHead)191 {192 //缓存当前节点的指针域193 tap = pHead->next;194 //释放当前结点195 free(pHead);196 //指针下移197 pHead = tap;198 }199 return 0;200 }201 202 203 int main(void)204 {205 int ret = 0;206 SLIST *pHead = NULL;207 208 //创建链表209 pHead = Slist_create();210 ret = Slist_printf(pHead);211 //给链表中插入元素212 ret = Slist_NodeInsert(pHead, 20, 19);213 ret = Slist_printf(pHead);214 //删除链表中某个元素215 ret = Slist_NodeDel(pHead, 19);216 ret = Slist_printf(pHead);217 //重置链表中的元素218 ret = Slist_Reverse(pHead);219 ret = Slist_printf(pHead);220 //销毁链表221 ret = Slist_Destory(pHead);222 223 return 0;224 225 }
1.结构体的基本特点:(结构体中可以嵌套一个别的结构体; ..........可以嵌套一个别的结构体指针)
(结构体中不可以嵌套一个自身类型的结构体(原因:确定不了结构体的内存大小);
..........可以嵌套一个指向自身类型的指针(原因:不同类型的指针在同一操作平台下所占内存相同,有确定值)
2.数据类型的本质:固定大小的内存块别名。
3.链表的基础特点:(结构体; 两个域:数据域、指针域; 引用自身的结构体; 特点:非线性存储)
4.链表编程关键两点:
1)指针指向谁,就把谁的地址赋给指针
2)辅助指针变量&操作逻辑的关系(辅助指针:pHead(头节点) pPre(前驱结点) pCur(当前结点) pM(业务节点))
=========================================================
此段代码刚开始是: 两个文件.C 和 一个.h文件,传代码由于不方便放到一个.C文件。
编写这段代码时,最难理解的是辅助节点的建立和移动。 编写错误的:167 pCur->next = pPre;(正确写法)
pCur->next = pPre->next;(错误写法:这种写法造成对第二元素的循环打印,死循环。)
63 if (NULL == pHead);(正确写法) if (NULL == tap); (错误写法:这种写法造成程序崩溃;)。