版权声明:本文为小斑马伟原创文章,转载请注明出处!
一、数组的缺陷
数组的缺陷1:静态空间,一旦分配内存后,不可以动态扩展。如果分配少了,可能不够用,如果分配多了,可能造成浪费。
数组缺陷2:对头部删除和插入、效率很低。因为头部数据插入和删除,要移动数据。
二、链表的基本概念
链表的组成:链表是由节点组成的,节点由数据域和指针域组成。
链表的分类:方式1:静态链表 动态链表 方式2:单向链表 双向链表 单向循环链表和双向循环链表。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//1.静态链表
//节点的声明
struct LinkNode
{
int num; //数据域
struct LinkNode* next; //指针域
};
void test01()
{
//创建节点
struct LinkNode node1 = { 10, NULL };
struct LinkNode node2 = { 20, NULL };
struct LinkNode node3 = { 30, NULL };
struct LinkNode node4 = { 40, NULL };
struct LinkNode node5 = { 50, NULL };
//建立关系
node1.next = &node2;
node2.next = &node3;
node3.next = &node4;
node4.next = &node5;
node5.next = NULL;
//如何遍历这个链表
//创建一个指针 指向第一个节点
struct LinkNode* pCurrent = &node1;
while (pCurrent != NULL) {
printf("%d\n", pCurrent->num);
pCurrent = pCurrent->next;
}
}
//动态链表
void test2() {
struct LinkNode* node1 = malloc(sizeof(struct LinkNode));
struct LinkNode* node2 = malloc(sizeof(struct LinkNode));
struct LinkNode* node3 = malloc(sizeof(struct LinkNode));
struct LinkNode* node4 = malloc(sizeof(struct LinkNode));
struct LinkNode* node5 = malloc(sizeof(struct LinkNode));
node1->num = 10;
node2->num = 30;
node3->num = 50;
node4->num = 70;
node5->num = 90;
//建立关系
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = node5;
node5->next = NULL;
//遍历链表
struct LinkNode* pCurrent = node1;
while (pCurrent != NULL) {
printf("%d\n", pCurrent->num);
pCurrent = pCurrent->next;
}
}
int main() {
test01();
printf("\n");
test2();
system("pause");
return EXIT_SUCCESS;
}
静态链表 创建在栈上 动态链表 创建在堆上
三、带头和不带头的链表
带头节点链表:固定一个节点作为头结点(数据域不保存有效数据),起一个标志位的作用,以后不管链表节点如何改变,此头节点固定不变。
不带节点的链表:头节点不固定,根据实际需要交换头节点(如在原来头节点前插入新节点,然后,新节点重新作为链表的头节点)。
带头节点的链表的初始化和遍历
#include<string.h>
#include<stdlib.h>
//节点声明
struct LinkNode
{
int num;
struct LinkNode *next;
};
//初始化链表
struct LinkNode* init_LinkList();
//遍历链表
void foreach_LinkList(struct LinkNode* pHeaher);
//插入链表
void insert_LinkList(struct LinkNode* pHeaher, int oldValue, int newValue);
//删除链表
void delete_LinkList(struct LinkNode* pHeader, int val);
//清空链表
void clear_LinkList(struct LinkNode* pHeader);
//销毁链表
void destory_LinkList(struct LinkNode* pHeader);
插入链表、删除链表、清空和销毁链表
#include"linkList.h"
struct LinkNode* init_LinkList()
{
struct LinkNode* pHeader = malloc(sizeof(struct LinkNode));
if (pHeader == NULL)
{
return NULL;
}
//pHeader->num = -1; 头节点不维护数据域
pHeader->next = NULL;//头节点初始化指针域为NULL
//创建一个尾节点,利用后期添加新的数据
struct LinkNode* pTail = pHeader;
int val = -1;
while (1) {
printf("请插入数据 -1代表输入结束:\n");
scanf("%d", &val);
if (val == -1)
{
break;
}
//创建新的节点
struct LinkNode* newNode = malloc(sizeof(struct LinkNode));
newNode->num = val;
newNode->next = NULL;
//建立关系
pTail->next = newNode;
//更新新的尾节点
pTail = newNode;
}
return pHeader;
}
//遍历链表
void foreach_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return;
}
//pCurrent 起始指向的是第一个有真实数据的节点
struct LinkNode* pCurrent = pHeader->next;
while (pCurrent != NULL)
{
printf("%d\n", pCurrent->num);
pCurrent = pCurrent->next;
}
}
//插入链表
void insert_LinkList(struct LinkNode* pHeader, int oldVal, int newVal)
{
if (pHeader == NULL)
{
return;
}
//创建两个辅助指针变量
struct LinkNode* pPrev = pHeader;
struct LinkNode* pCurrent = pHeader->next;
while (pCurrent != NULL)
{
if (pCurrent->next == oldVal)
{
break;
}
//如果没有找到位置,让辅助指针右移
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
//创建新节点
struct LinkNode* newNode = malloc(sizeof(struct LinkNode));
newNode->num = newVal;
newNode->next = NULL;
//建立关系 更新指针的指向
newNode->next = pCurrent;
pPrev->next = newNode;
}
//删除链表
void delete_LinkList(struct LinkNode* pHeader, int val)
{
if (pHeader == NULL)
{
return;
}
//创建两个辅助的指针变量
struct LinkNode* pPrev = pHeader;
struct LinkNode* pCurrent = pHeader->next;
while (pCurrent != NULL)
{
if (pCurrent->num == val)
{
break;
}
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
//无效数据 就直接return
if (pCurrent == NULL)
{
return;
}
//更改指针的指向
pPrev->next = pCurrent->next;
//删除节点
free(pCurrent);
pCurrent = NULL;
}
//清空链表
void clear_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return;
}
//创建临时指针
struct LinkNode* pCurrent = pHeader->next;
while (pCurrent != NULL)
{
//先保存住待删除节点的后面的节点
struct LinkNode* nextNode = pCurrent->next;
free(pCurrent);
pCurrent = nextNode;
}
//头节点的next置空
pHeader->next = NULL;
}
//销毁链表
void destory_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return;
}
//先清空链表
clear_LinkList(pHeader);
//再释放头节点
free(pHeader);
pHeader = NULL;
}
void test01()
{
//初始化链表
struct LinkNode* pHeader = init_LinkList();
//遍历链接
printf("遍历链表的结果为\n");
foreach_LinkList(pHeader);
//插入数据
//10 20 30
insert_LinkList(pHeader, 10, 100);
insert_LinkList(pHeader, 20, 200);
insert_LinkList(pHeader, -1, 300);
//插入后数据的遍历
printf("遍历链表的结果为\n");
foreach_LinkList(pHeader);
//测试删除
delete_LinkList(pHeader, 30);
delete_LinkList(pHeader, 100);
delete_LinkList(pHeader, 1000);
//删除后的数据
printf("遍历链表的结果为\n");
foreach_LinkList(pHeader);
//清空链表
clear_LinkList(pHeader);
//清空后的数据
printf("遍历链表的结果为\n");
foreach_LinkList(pHeader);
//尾插
insert_LinkList(pHeader, 111, 111);
insert_LinkList(pHeader, 222, 222);
insert_LinkList(pHeader, 333, 333);
//清空后再次使用链表,遍历链表
foreach_LinkList(pHeader);
//销毁链表
destory_LinkList(pHeader);
pHeader = NULL;
}
int main() {
test01();
system("pause");
return EXIT_SUCCESS;
}
链表的反转和计算其个数
//反转链表
void reverse_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return;
}
struct LinkNode * pPrev = NULL;
struct LinkNode * pCurrent = pHeader->next;
struct LinkNode * pNext = NULL;
while (pCurrent != NULL)
{
pNext = pCurrent->next;
pCurrent->next = pPrev; //改变链表指向
pPrev = pCurrent;
pCurrent = pNext;
}
pHeader->next = pPrev;
}
//返回链表长度
int size_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return -1;
}
struct LinkNode* pCurrent = pHeader->next;
int num = 0;
while (pCurrent != NULL)
{
num++;
pCurrent = pCurrent->next;
}
return num;
}
void test02()
{
struct LinkNode* pHeader = init_LinkList();
// 10 20 30
//翻转后 结果应该是 30 20 10
reverse_LinkList(pHeader);
printf("翻转链表后结果为\n");
foreach_LinkList(pHeader);
printf("链表的长度为: %d\n", size_LinkList(pHeader));
}