三、C语言实现头指针的单链表
1、逻辑图
头指针会使用到二级指针
使用二级指针的逻辑图
2、声明
#pragma once
//结构声明
typedef int DataType;
typedef struct Node
{
DataType data; //记录本结点的数据
struct Node* next;//记录下一个结点的地址
}Phead_List;
//方法声明
//初始化
bool InitPheadList(Phead_List** p);
//判空
bool IsEmpty(Phead_List** p);
//求长度
int GetLength(Phead_List** p);
//开辟新结点
static Phead_List* ApplyNewNode(DataType value, Phead_List* next);
//头插法
bool InsertOfHead(Phead_List** p, DataType value);
//按位置插入
bool InsertOfPos(Phead_List** p, DataType value, int pos);
//尾插法
bool InsertOfRear(Phead_List** p, DataType value);
//头删
bool DeleteOfHead(Phead_List** p);
//尾删
bool DeleteOfRear(Phead_List** p);
//删除元素(按位置删除)
bool DeleteOfPos(Phead_List** p, int pos);
//输出
void ShowList(Phead_List** p);
//销毁
void DestoryList(Phead_List** p);
3、方法实现
#include<stdio.h>
#include<stdlib.h>
#include"Phead_List.h"
//函数实现
//初始化
bool InitPheadList(Phead_List** p)
{
//传参时,p的值就是主函数中的Phead地址
if (p == NULL) return false;
*p = NULL; //指向头结点的指针置空
}
//判空
bool IsEmpty(Phead_List** p)
{
if (p == NULL) return false;
if (*p == NULL) return true;
return false;
}
//求长度
int GetLength(Phead_List** p)
{
if (p == NULL) exit(0);
int count = 0;
Phead_List* q = *p;
while (q != NULL)
{
count++;
q = q->next;
}
return count;
}
//开辟新结点
static Phead_List* ApplyNewNode(DataType value,Phead_List *next)
{
Phead_List* newspace = (Phead_List*)malloc(sizeof(Phead_List));
if (newspace == NULL) exit(0);
newspace->data = value;
newspace->next = next;
return newspace;
}
//头插法
bool InsertOfHead(Phead_List** p, DataType value)
{
if (p == NULL) return false;
Phead_List* newnode = ApplyNewNode(value, *p);
*p = newnode;
return true;
}
//按位置插入
bool InsertOfPos(Phead_List** p, DataType value, int pos)
{
if (p == NULL) return false;
if (pos<0 || pos>GetLength(p)) return false;
//当pos为0时,需特殊处理,改用头插,以为此时要修改头指针的值
if (pos == 0) return InsertOfHead(p, value);
//先找到pos位置
Phead_List* q = *p; //记录第一个结点地址
while (pos>1) //找到pos位置的前一个结点
{
q = q->next;
pos--;
}
Phead_List* newnode = ApplyNewNode(value, q->next);
q->next = newnode;
return true;
}
//尾插法
bool InsertOfRear(Phead_List** p, DataType value)
{
if (p == NULL) return false;
return InsertOfPos(p, value, GetLength(p));
}
//头删
bool DeleteOfHead(Phead_List** p)
{
if (p == NULL) return false;
if (IsEmpty(p)) return false;
Phead_List* q = *p;
*p = q->next;
free(q);
q = NULL;
return true;
}
//尾删
bool DeleteOfRear(Phead_List** p)
{
if (p == NULL) return false;
if (IsEmpty(p)) return false;
Phead_List* q = *p;
Phead_List* front = NULL;//保存q的前驱节点
while (q->next!=NULL)
{
front = q;
q = q->next;
}
//如果只剩一个结点
if (front == NULL) return DeleteOfHead(p);
front->next = NULL;
free(q);
q = NULL;
return true;
}
//删除元素(按位置删除)
bool DeleteOfPos(Phead_List** p, int pos)
{
if (p == NULL) return false;
if (pos<0 || pos>GetLength(p) - 1) return false;
if (IsEmpty(p)) return false;
if (pos == 0) return DeleteOfHead(p);
if (pos == GetLength(p) - 1) return DeleteOfRear(p);
//同样找到要删除的pos的前驱结点
Phead_List* q = *p; //保存头结点地址
while (pos>1)
{
q = q->next;
pos--;
}
Phead_List* s = q->next; //保存q的后继节点(要删除的结点)
q->next = s->next;
free(s);
s = NULL;
return true;
}
//输出
void ShowList(Phead_List** p)
{
if (p == NULL) exit(0);
Phead_List* q = *p;
while (q != NULL)
{
printf("%d ", q->data);
q = q->next;
}
printf("\n");
}
//销毁
void DestoryList(Phead_List** p)
{
if (p == NULL) exit(0);
while (!IsEmpty(p))
{
DeleteOfHead(p); //头删时间复杂度为O(1)
}
}
4、主函数测试
#include<stdio.h>
#include"Phead_List.h"
int main()
{
//在栈区
Phead_List* phead;//头指针,保存第一个结点的地址
//初始化
InitPheadList(&phead);
//头、尾、头插入
InsertOfHead(&phead, 56);
InsertOfRear(&phead, 34);
InsertOfHead(&phead, 78);
ShowList(&phead);
//按位置插
InsertOfPos(&phead, 66, 3);
InsertOfPos(&phead, 43, 2);
ShowList(&phead);
//尾、头删
DeleteOfRear(&phead);
DeleteOfHead(&phead);
ShowList(&phead);
//按位置删除
DeleteOfPos(&phead, 2);
ShowList(&phead);
DestoryList(&phead);
return 0;
}
5、测试结果
6、在实现插入和删除元素时注意考虑多种情况
插入情况
删除情况