单向链表

浪尽此生 提交于 2019-11-28 07:28:49

链表的操作不外乎 增 删 改 查 还能有个额外的打印

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 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!