链表的操作不外乎 增 删 改 查 还能有个额外的打印
1. 头插 , 2.尾插 , 3.中端插入 4.头删 5.尾删 6.中段删除 7.查 8. 改 9.反转打印 10.反转链表 11.判断链表是否有环 12.合并两个有序链表 13.链表排序(选择)
链表节点结构
1 typedef struct _T_LINKNODE{ 2 int data; 3 _T_LINKNODE* pNext; 4 }T_LINKNODE, *PT_LNode;
创建节点并初始化
1 PT_LNode creadNode() //创建节点 2 { 3 PT_LNode pNew = (PT_LNode)malloc(sizeof(T_LINKNODE)); 4 init(pNew); 5 return pNew; 6 } 7 8 void init(PT_LNode pHead) //初始化 9 { 10 pHead->data = 0; 11 pHead->pNext = NULL; 12 }
增 : 头插 尾插 和查找插入 头节点可以用于计数节点个数
1.头插: 新节点的next 指向头节点的next 头节点的next指向新节点
1 int insertHead(PT_LNode pHead, int data) //头插 头节点计数 2 { 3 if (isEmpty(pHead)) 4 { 5 insertBack(pHead, data); 6 return ++(pHead->data); 7 } 8 else 9 { 10 PT_LNode pNew = creadNode(); 11 pNew->data = data; 12 pNew->pNext = pHead->pNext; 13 pHead->pNext = pNew; 14 return ++(pHead->data); 15 } 16 }
2.尾插: 创建一个同链表的结构一样的类型指针(不需要malloc) 利用循环找到next指向NULL的指针 , 把指向NULL的指针指向新节点 完成插入.
1 int insertBack(PT_LNode pHead, int data) //尾插 头节点计数 2 { 3 PT_LNode p = pHead; 4 while (p->pNext) 5 { 6 p = p->pNext; 7 } 8 PT_LNode pNew = creadNode(); 9 pNew->data = data; 10 p->pNext = pNew; 11 return ++(pHead->data); 12 }
3.查找插入: 先判断要查找的数据是否存在 ,可以利用查找函数返回的指针用作插入 (特殊情况 , 如果满足头插和尾插的条件可以分别调用写好函数插入)
1 int insertNode(PT_LNode pHead, int Fdata, int newData) 2 { 3 4 PT_LNode tempNode = findData(pHead, Fdata); //findData在下面 5 6 PT_LNode pNew = creadNode(); 7 pNew->data = newData; 8 if ((!tempNode->pNext) && (tempNode->data == Fdata)) 9 { 10 insertBack(pHead, newData); 11 } 12 else 13 { 14 pNew->pNext = tempNode->pNext; 15 tempNode->pNext = pNew; 16 return ++(pHead->data); 17 } 18 }
删除节点 , 和插入一 一对应 删除的数据返回出来以备不时之需
4.头删除: 使用临时指针 指向要删除的节点 头指针再指向删除节点的next重新链接链表
1 int deleteHead(PT_LNode pHead) 2 { 3 int temp; 4 PT_LNode p = pHead->pNext; 5 pHead->pNext = p->pNext; 6 temp = p->data; 7 free(p); 8 p = NULL; 9 --pHead->data; 10 return temp; 11 }
5.尾删除: 利用循环找到末尾的上一个节点 直接free掉末尾 , 末尾的上一个节点指向NULL
1 int deleteBack(PT_LNode pHead) 2 { 3 int temp; 4 PT_LNode p = pHead; 5 while (p->pNext->pNext) 6 { 7 p = p->pNext; 8 } 9 temp = p->pNext->data; 10 free(p->pNext); 11 p->pNext = NULL; 12 --pHead->data; 13 return temp; 14 }
6.查找删除节点: 找到要删除的当前节点的上一个节点 , 用一个临时节点指向当前节点 , 把当前节点的上一个节点 指向 当前节点的下一个节点 , 再free掉临时节点置空
1 int temp; 2 PT_LNode p = pHead->pNext; 3 while (p->pNext) 4 { 5 if (p->pNext->data == deleteData) 6 { 7 break; 8 } 9 p = p->pNext; 10 } 11 if ((!p->pNext) && (p->data == deleteData)) 12 { 13 deleteBack(pHead); 14 } 15 else if ( p == pHead->pNext && p->data == deleteData) 16 { 17 deleteHead(pHead); 18 } 19 else 20 { 21 PT_LNode pTemp = p->pNext; 22 p->pNext = pTemp->pNext; 23 temp = pTemp->data; 24 free(pTemp); 25 pTemp->pNext = NULL; 26 --pHead->data; 27 return temp; 28 }
7.改之前先查: 遍历所有节点 找到符合条件的节点(要找的数据节点)并返回指向要找节点的指针
1 PT_LNode findData(PT_LNode pHead, int Fdata) //返回要查找数据的指针 2 { 3 PT_LNode p = pHead; 4 bool flag = true; 5 while (p->pNext) 6 { 7 if (p->data == Fdata) 8 { 9 break; 10 } 11 else 12 { 13 p = p->pNext; 14 } 15 } 16 (!p->pNext) && (p->data != Fdata) ? flag = false : flag; 17 if (flag) 18 { 19 printf("要查找的数据存在\n"); 20 return p; 21 } 22 else 23 { 24 printf("要查找的数据不存在\n"); 25 return NULL; 26 } 27 }
8.改: 利用查找函数返回的指针赋值
1 void changeData(PT_LNode pHead, int Fdata, int newData) 2 { 3 PT_LNode pTemp = findData(pHead, Fdata); 4 if (!pTemp) 5 { 6 printf("数据不存在\n"); 7 return ; 8 } 9 else 10 { 11 pTemp->data = newData; 12 } 13 }
9.反转打印(递归法)
1 void reversalPrint(PT_LNode pHead) 2 { 3 if (!pHead) 4 { 5 return; 6 } 7 reversalPrint(pHead->pNext); 8 printf("%d<-", pHead->data); 9 }
10.反转链表(递归法) : 递归逐层进入到最里层(递归边界 next == NULL) 再从最里层的next开始逐层向外指后 ,
当前节点制空 并 返回指向当前层的指针(当前节点是pHead)
1 PT_LNode reversalList(PT_LNode pHead) 2 { 3 if (!pHead->pNext || !pHead) 4 { 5 return pHead; 6 7 } 8 PT_LNode pTemp = reversalList(pHead->pNext); //传入当前节点pHead进入递归 并 另存当前节点 9 pHead->pNext->pNext = pHead; //当前节点指向上一个节点 10 pHead->pNext = NULL; //把上一个节点制空 11 return pTemp; //返回当前节点 , 用作上一层递归 12 }
11.判断单链表是否有环 用两个指针都指向头节点 , 从第一个开始p1每次都比p2快一个节点 , 如果有环则会相遇
1 bool judgeCircle(PT_LNode pHead) 2 { 3 PT_LNode p1, p2; 4 p1 = pHead; p2 = pHead; 5 while (p1->pNext && p2->pNext) 6 { 7 8 p2 = p2->pNext; 9 p1 = p1->pNext->pNext; 10 if (p1 == p2) 11 { 12 return true; 13 } 14 } 15 return false; 16 }
12.合并两个有序递增的链表: 1对1 2对2 的比较大小 , 小的先插入新链表以此类推 ,因为链表是有序递增的 比较剩下的一定比插入好的大
所以依次插入新链表
1 PT_LNode mergeList(PT_LNode pHead3, PT_LNode pHead1, PT_LNode pHead2) 2 { 3 PT_LNode p1 = pHead1; 4 PT_LNode p2 = pHead2; 5 while (p1 || p2) //必须两个链表都遍历完 6 { 7 if (p1 && p2) 8 { 9 if (p1->data < p2->data) //1对1 2对2 彼此对应比较 较小的放前面 10 { 11 insertBack(pHead3, p1->data); 12 p1 = p1->pNext; 13 } 14 else 15 { 16 insertBack(pHead3, p2->data); 17 p2 = p2->pNext; 18 } 19 } 20 else //链表节点数量不相同 , 则把后面的都插入 , 因为是链表已经是有序的 , 前面比较都是比后面的小 , 所以剩余的节点全部依次插入新链表 21 { 22 while (p1) 23 { 24 insertBack(pHead3, p1->data); 25 p1 = p1->pNext; 26 } 27 while (p2) 28 { 29 insertBack(pHead3, p2->data); 30 p2 = p2->pNext; 31 } 32 break; //链表遍历完成 退出遍历 33 } 34 } 35 return pHead3; //返回新链表 36 }
13.链表的排序(选择) : p1第一次循环把第一个数据和后面的全部一 一比较(满足条件交换) p1第二次循环把第二个和后面都比较,以此类推 时间复杂度O(n^2)
1 void ListSort(PT_LNode pHead) 2 { 3 PT_LNode p1, p2; 4 int temp; 5 for (p1 = pHead->pNext; p1->pNext; p1 = p1->pNext) 6 { 7 for (p2 = p1->pNext; p2; p2 = p2->pNext) 8 { 9 if (p1->data > p2->data) 10 { 11 temp = p1->data; 12 p1->data = p2->data; 13 p2->data = temp; 14 } 15 } 16 } 17 }