C++学习(三十五)(C语言部分)之 单链表

 单链表 就好比火车

火车头-->链表头部
火车尾-->链表尾部
火车厢-->链表的节点
火车厢连接的部分-->指针
火车中的内容-->链表节点的的数据
链表节点包含数据域和指针域
数据域存放数据
指针域存放要连接的节点的首地址

在造火车的时候 先是火车头 然后是车厢
--->链表的首节点和之后的节点

先从内存中申请头结点的存储空间
--->PLTST phead=(PLTST)malloc(sizeof(LTST));
首节点在创建时会让指针域指向空
--->既链表的初始化

链表连接的规则,要先连接后断开
对于单链表的插入有两种方法
1、头插法
2、尾插法(比较简单的)

尾插法 申请好一个新的节点后将链表的最后一个节点的指针域指向新节点

头插法 首先创建新节点,找到链表头节点,将指针指向新节点,将新节点指针指向第二节点

单链表测试代码笔记如下:

  1 #include<stdio.h>
  2 #include <stdlib.h> //malloc 要用到
  3 
  4 typedef struct Node
  5 {
  6     int data;  //数据域:用来存放数据
  7     struct Node* pNext;  //指针域:用来存储下一个结点地址
  8 }LIST,*PLIST;
  9 
 10 //1. 创建一个火车头.  相当于创建链表 =用函数来创建一个链表的头部
 11 //创建链表的头部
 12 PLIST CreateListHead()
 13 {
 14        //1.1 申请内存
 15     PLIST phead = (PLIST)malloc(sizeof(LIST));
 16     //1.2 判断是否申请成功
 17     if (NULL == phead)
 18     {
 19         printf("头结点的内存申请失败!
");
 20         return NULL; 
 21     }
 22     phead->pNext = NULL;
 23     //phead->data   可以赋值也可以不赋值,因为头结点不存储数据
 24     //.它只是用来标记链表的头部
 25     //有表头的链表头结点都不存储数据,只是用来标记链表的头部
 26     return phead;
 27 }
 28 
 29 //2.写一个创建结点的函数,用来申请结点内存
 30 PLIST CreateListNode(int data)
 31 {
 32     PLIST newNode = (PLIST)malloc(sizeof(LIST));
 33     if (NULL == newNode)
 34     {
 35         printf("结点内存申请失败!
");
 36         return NULL;
 37     }
 38     newNode->pNext = NULL;
 39     newNode->data = data;
 40     return newNode;
 41 }
 42 
 43 //3.插入一个结点   头部插入  指定位置插入  尾部插入
 44 void InsertListHead(PLIST p_list, int data)//1. 要说明要插入的链表是哪一个 2.要插入的数据
 45 {
 46     //3.1 申请一个结点
 47     PLIST node = CreateListNode(data);
 48     //先连接后断开
 49     node->pNext = p_list->pNext;
 50     p_list->pNext = node;
 51 }
 52 
 53 //4. 尾插法
 54 void InsertListTail(PLIST p_list, int data)
 55 {
 56     //4.1 申请结点内存
 57     PLIST node = CreateListNode(data);
 58     //我们只知道链表的头部  尾部就要去遍历得到
 59     PLIST p_Temp = p_list;
 60     //遍历找到尾结点
 61     while (p_Temp->pNext!=NULL)  //  表达式非0就是真
 62     {
 63         p_Temp = p_Temp->pNext;
 64     }
 65     //循环结束 就是找到了最后一个结点
 66     node->pNext = NULL;
 67     p_Temp->pNext = node;
 68 }
 69 
 70 //在链表p_list中的pos位置插入data
 71 void InsertListAppoint(PLIST p_list, int pos, int data)
 72 {
 73     PLIST node = CreateListNode(data);
 74     PLIST p_Temp1 = p_list;
 75     PLIST p_Temp2 = p_list;
 76     for (int i = 0; i < pos; i++)
 77     {
 78         if (p_Temp1->pNext != NULL)
 79         {
 80             p_Temp1 = p_Temp1->pNext;
 81             if (i>0)
 82             p_Temp2 = p_Temp2->pNext;
 83         }
 84         else
 85         {   //如果pos大于链表结点的个数,就插入到尾部
 86             p_Temp1->pNext = node;
 87             node->pNext = NULL;
 88             return;   //退出函数 不往下执行
 89         }
 90     }
 91     //循环结束  --> 说明我找到了我要插入的位置
 92     node->pNext = p_Temp1;
 93     p_Temp2->pNext = node;
 94 
 95 }
 96 
 97 //  遍历链表的每一个结点
 98 void PrintList(PLIST p_list)
 99 {
100     PLIST p_Temp = p_list->pNext; //从头部的下一个结点开始输出里面的数据
101     while (p_Temp)
102     {
103         printf("%d -> ", p_Temp->data);//打印结点里面的数据
104         p_Temp = p_Temp->pNext;
105     }
106     printf("NULL
");
107 }
108 //删除    删除头结点  指定位置删除  尾部删除
109 //知道这个逻辑     多画图 多写代码  
110 //后面还会有双向循环链表 要处理四个指针  现在只需要处理两个 双向循环链表不画图很难理解
111 //画图之后会发现很简单 只需要照着画的图去链接各个指针就OK了
112 void DeleteListHead(PLIST p_list)  //PLIST p_list=head.
113 {
114     PLIST p_Temp = p_list->pNext;
115     //先链接还是先释放 
116     p_list->pNext = p_Temp->pNext;  //连接
117     free(p_Temp);
118 }
119 
120 //不用循环 删除所有结点
121 void DeleteList(PLIST p_list)//函数会执行5  5 4 3 2 1
122 {
123     //满足条件的情况下 自己调用自己
124     if (p_list->pNext!=NULL)   //if括号里面不是0就是成立
125     {
126         DeleteList(p_list->pNext);
127     }
128     free(p_list);
129 
130 }
131 
132 int fun(int n)
133 {
134     if (n == 1)
135     {
136         return 1;
137     }
138     else
139     {
140         return n + fun(n - 1);
141     }  //5 +4+3+2+1    //函数嵌套调用
142     for (int i = 0; i < 5; i++)
143     {
144         for (int j = 1; j < 5; j++)
145         {
146               ///内循环结束又回到了外循环
147         }
148     }
149 }
150 
151 int main()
152 {
153     PLIST head = CreateListHead();  //创建头部 把堆内存的首地址返回给head
154     for (int i = 1; i <= 5; i++)
155         InsertListHead(head, i);
156     PrintList(head);
157 
158     ////尾插法
159     //InsertListTail(head, 98);
160     //PrintList(head);
161 
162     ////指定位置插入
163     //InsertListAppoint(head, 2, 520);
164     //PrintList(head);
165     //InsertListAppoint(head, 88, 520);
166     //PrintList(head);
167     //DeleteListHead(head);
168     //PrintList(head);
169 
170     DeleteList(head);
171     PrintList(head);
172     head = NULL;
173     return 0;
174 }

 附:

原文地址:https://www.cnblogs.com/Yuuki-/p/10634409.html