链表基本操作
程序员文章站
2024-03-19 15:46:04
...
今天上课男神讲了链表,可以说是非常懵逼。为了防止遗忘及时整理,但个人感觉理解的还是不太到位。
话不多说,开始正题。
链表通过一个结构体来构建:
typedef struct node{
int data;
struct node * next;
}Node;
几种功能函数的手写:
首先是最简单的打印链表函数printList:
/*打印链表元素的函数,传入首节点地址即可*/
void printList(Node * head)
{
for(; head; ){
printf("%d ", head ->data);
head = head -> next;
}
puts("");
}
链表长度 sizeList:
/*统计链表长度*/
int sizeList(Node *head)
{
int i;
for(i = 0; head; ++i)
head = head ->next;
return i;
}
尾部插入
/*尾部插入法*/
/*
*尾部插入分两种情况
* ① list存在(一般情况)
* ② list是空链表插入的元素是链表的第一个元素
* 步骤: 动态分配内存创建一个新的链表(结构体成员)
* 然后根据实际链表情况将新创建的链表放到原链表的末尾
*/
//形参列表 由于函数要修改指针的指向 所以应该用二级指针来操作一级指针!
void pushBacklist(Node **plist, int data)
{
//创先新链表单元
Node * newNode = (Node *)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
//核心插入 分两种情况
//一般情况,List不为空链表, 那就往后找直到最后一个。
if(*plist != NULL){
Node * temp = * plist;
while(temp ->next != NULL)
temp = temp ->next;
temp ->next = newNode;
}
//空链表的情况
else{
*plist = newNode;
}
}
首部插入法:
/*首部插入法*/
void pushFrontlist(Node ** plist, int data)
{
//同样先建创建新的链表单元
Node * newNode = (Node *)malloc(sizeof(Node));
newNode ->data = data;
newNode ->next = *plist;
//插入 只有一种情况直接赋值即可
*plist = newNode;
}
清空链表操作
/*清空链表*/
/*想要清空链表仍然要对指向链表的指针进行操作,故形参列表要传二级指针!
* 清空链表要维护两个指针,一个指针(temp)负责free该单元的,另一个指针
*(head)要指向下一个单元,两指针共同向前移动直到释放最后一个链表单元。
*/
void freeList(Node **plist)
{
Node * head = *plist;
Node * temp;
while(head != NULL){
temp = head;
head = head->next;
free(temp);
}
//切记清空 *plist
*plist = NULL;
}
删除特定单元:
/*删除链表中某特定值data值的单元*/
/*
*要从第一个链表的data开始依次比对data值与目标值是否相符,如果相符
*就删去,否则continue。
*/
void deletData(Node ** plist, int data)
{
Node * head = *plist;
Node * temp;
while(head ->next != NULL){
//如果不是目标data,就指向下一个节点
if(head ->next->data != data){
head = head ->next;
continue;
}
//如果是目标data,进行删除操作
temp = head ->next;
head ->next = temp ->next;
//删除目标节点
free(temp);
}
//最后对第一个节点进行操作
if((*plist) ->data == data){
temp = *plist;
*plist = temp ->next;
free(temp);
}
}
附上完整的测试样例
int main(void)
{
Node n1, n2, n3, n4;
n1.data = 10;
n2.data = 20;
n1.next = &n2;
n2.next = NULL;
printList(&n1); //10
printf("%d\n", sizeList(&n1)); //20
//维护一个动态指针
Node * list = NULL;
printf("尾插后的数组是:\n");
pushBacklist(&list, 10);
pushBacklist(&list, 20);
pushBacklist(&list, 30);
printList(list); //10 20 30
printf("首插后的数组是:\n");
pushFrontlist(&list, 80);
pushFrontlist(&list, 90);
printList(list); //90 80 10 20 30
printf("释放链表:\n");
freeList(&list);
pushBacklist(&list, 100);
printList(list);//100
freeList(&list);
puts("==========================");
printf("验证删除链表元素\n");
pushBacklist(&list, 1);
pushBacklist(&list, 1);
pushBacklist(&list, 2);
pushBacklist(&list, 3);
pushBacklist(&list, 4);
pushBacklist(&list, 4);
pushBacklist(&list, 5);
pushBacklist(&list, 5);
puts("删除前:");
printList(list);
puts("删除1");
deletData(&list, 1);
puts("删除后:");
printList(list);
return 0;
}
上一篇: Spring Security中的自定义用户登录页面
下一篇: 循环单链表