目录
五:单链表的实现(每次创建新的节点,都要把节点的next域置为空)
一:节点的创建
c中通过结构体来创建节点
我们以单链表来举例,看下面代码,这是创建了一个结点的结构体类型
typedef struct node {//结构体的创建
int date;//数据域
struct Node* next;//指针域
}Node,*Link;//别名,一个是结构体类型,一个是结构体类型的指针
我们通过malloc来创建一个结点要引用#include<malloc.h>这个头文件
malloc函数的返回值是void*万能指针类型,这个指针类型不能够运算,可以强制转化成任意类型
由于l1是Link类型的,所以转化为Link类型的
Link l1=(Link) malloc(sizeof(Node));//创建一个结点,malloc的返回值是void*可强制转化为任意类型
二:链表的遍历
我们通过移动指针来实现链表的遍历,这个比较容易,但不是p++这种,因为链表在逻辑上是连续的,在物理的存储上是不连续的,看下面代码,这里是有头节点的,头节点的下一个结点才存储着数据
void Display(Link l1) {//单链表的遍历操作
Link p = l1->next;
while (p) {//判断p是否为空
printf("%d ", p->date);
p = p->next;
}
}
三:求单链表的元素个数
这个还是遍历
int Num(Link l1) {//从头节点开始计算,如果从首元结点算的话count=1
int count = 0;
while (l1) {//判断l1是否为空
l1 = l1->next;
count++;
}
return count;
}
四:单链表的插入与删除以及释放所有节点
插入
前驱比后继好用,嗷嗷好用
指针指向的是插入节点的前一个节点,也就是前驱
int insertNode(Link l1, int n, int x) {//l1是链表的头指针,n是插入的位置,x是插入的数据
int count = 0;//记录指针走到了哪里
Link p = l1->next;
while (p != NULL && count < n - 1) {//n为插入的位置,我们需要把指针移到前驱位置,因为前驱比
//后继好用 [0-n-1)是n-1个数
p = p->next;
count++;
}
if (p == NULL) {//链表不够长
return 0;
}
else {
Link node = (Link)malloc(sizeof(Node));//要插入的节点
node->date = x;
node->next = p->next;//插入算法
p->next = node;
}
return 1;
}
删除
需要两个指针一前一后的进行扫描,直到前面的指针扫描到要删除的节点处停止,在进行扫描前,要对链表进行非空判断
Link my_delete(Link head, int n) {
if (head == NULL || head->next == NULL) {//判断传进来的链表是否为空链表
return 0;
}
Link p = head->next;//初始化两个一前一后的指针
Link q = head;
while (p) {//防止越界
if (p->date == n) {//如果相等,就删除
q->next = p->next;
free(p);
return 1;
}
else {//两个指针向前移动
q = p;
p = p->next;
}
}
return 0;
}
释放所有节点
void my_free(Link head) {
while (head->next) {//不为空就释放
Link p = head;
head = head->next;
free(p);
}
free(head);//释放头节点
}
五:单链表的实现(每次创建新的节点,都要把节点的next域置为空)
头插法
假设我们有一个数组,里面有n个元素,我们需要把里面的元素放到一个单链表中
头插法插入元素的顺序是逆过来的
#include<stdio.h>
#include<malloc.h>
typedef struct node {
int date;
struct node* next;
}Node,*Link;
Link newList(int *arr, int n) {
Link head = (Link)malloc(sizeof(Node)) ;//创建头节点,并是指针域为空
head->next= NULL;
for (int i = 0; i < n; i++) {
Link node = (Link)malloc(sizeof(Node));//每次循环都创建一个新节点
node->date = *arr++;//将数组里的元素放进节点的数据域
node->next = head->next;//将节点的指针域置为空
head->next = node;//头节点指向新节点
}
return head;//返回头节点
}
int main() {
int arr[5] = { 1,2,3,4,5 };
Link p=newList(arr, 5);
while (p->next) {
p = p->next;
printf("%d ", p->date);
}
}
尾插法
Link newList2(int *arr, int n) {
Link head = (Link)malloc(sizeof(Node));//创建头节点,没创建一个节点,都要将他的指针与置为空
head->next = NULL;
Link rest = head;//刚开始的尾节点和头接待你在一个位置
for (int i = 0; i < n; i++) {
Link node = (Link)malloc(sizeof(Node));
node->date = *arr++;
rest->next = node;//将尾节点指针域指向新的节点
rest = node;//将尾节点指向新的节点
}
rest->next = NULL;//将尾节点的指针域置为空,否则会出现野指针,指向未知域
return head;
}