最近在重新学习数据结构并打算实现部分代码,仅以此系列记录一下对应的代码实现。
本次实现的是线性表的链式存储结构——单链表。
默认采用头结点。
头结点和头指针区别
不管带不带头结点,头指针始终指向链表的第一个结点,而头结点是带头结点的链表中的第一个结点,通常不存储任何信息。(可以存储链表长度)
引入头结点的两个好处:
1.由于第一个数据结点的位置被存放在头结点的指针域中,因此在链表的第一个位置上的操作和其他位置上的操作一致,无须进行特殊操作。
2.无论链表是否为空,其头指针始终指向头结点的非空指针,因此空表和非空表的处理也得到了统一,
代码部分
#include <iostream>
using namespace std;
// 代码默认带头结点
// ADT
// InitList(&L); //初始化表
// List_HeadInsert(&L);//头插法建立单链表
// List_TailInsert(&L);//尾插法建立单链表
// DestroyList(&L);//销毁表
// ListInsert(&L,i,e);//在位序i插入元素e
// InsertNextNode(*p,e);//在p节点之后插入元素e
// InsertPriorNode(*p,e);//在p节点之前插入元素e
// ListDelete(&L,i,&e);//删除位序i的元素,并返回
// DeleteNode(*p,&e);//删除指定节点
// GetElem(L,i);//按位查找,返回第i位元素的值
// LocateElem(L,e);//按值查找,返回值为e的元素的位序
// IsEmpty(L);//判断线性表是否为空
// PrintList(L);//顺序输出线性表
typedef struct LinkNode
{
int data;
LinkNode *next;
}LNode,*LinkList;
//初始化表
bool InitList(LinkList &L){
L=(LNode*)malloc(sizeof(LNode));
if(L==nullptr)//假设内存不足,返回false
return false;
L->next=nullptr;
return true;
}
//头插法建立单链表
bool List_HeadInsert(LinkList &L){
LNode*s;
int x;
if(InitList(L)){
scanf("%d",&x);//读取数字
while(x!=666){//输入数字为666即退出
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);//读取数字
}
return true;
}else{
return false;//创建失败
}
}
//尾插法建立单链表
bool List_TailInsert(LinkList &L){
LNode*s,*t;//这里s用作创建新节点,t始终指向尾结点
int x;
if(InitList(L)){
t=L;
scanf("%d",&x);//读取数字
while(x!=666){//输入数字为666即退出
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=nullptr;
t->next=s;
t=s;
scanf("%d",&x);//读取数字
}
return true;
}else{
return false;//创建失败
}
}
//销毁表
void DestroyList(LinkList &L){
LNode* p;
while(L){
p=L;
L=L->next;
free(p);
}
}
//在p节点之后插入元素e
bool InsertNextNode(LNode *p,int e){
if(p==nullptr) //如果p为空
return false;
LNode *temp=(LNode*)malloc(sizeof(LNode));
if(temp==nullptr) //内存分配不足
return false;
temp->data=e;
temp->next=p->next;
p->next=temp;
return true;
}
//在p节点之前插入元素e
// InsertPriorNode(*p,e);
//按位查找,返回第i位元素的节点地址
LNode* GetElem(LinkList L,int i){
if(i<0)
return nullptr;
LNode *p;
int j=0;
p=L;
while(p!=nullptr && j<i){
p=p->next;
j++;
}
return p;
}
//按值查找,返回值为e的元素的位
LNode* LocateElem(LinkList L,int e){
LNode* tmp=L->next;//略过头结点
while (tmp!=nullptr&&tmp->data!=e)
tmp=tmp->next;
return tmp;//tmp不为null代表找到了节点
}
//在位序i插入元素e
bool ListInsert(LinkList &L,int i,int e){
LNode* p=GetElem(L,i-1);//找到前一位节点
return InsertNextNode(p,e);
}
//删除位序i的元素,并返回
bool ListDelete(LinkList &L,int i,int &e){
LNode* p=GetElem(L,i-1);//找到前一位节点
LNode* q=p->next;//要删除的节点
p->next=q->next;
free(q);
return true;
}
//判断线性表是否为空
bool IsEmpty(LinkList L){
if(L->next==nullptr)
return true;
else
return false;
}
//顺序输出线性表
void PrintList(LinkList L){
if(!IsEmpty(L)){
LinkNode* tmp=L;
int i=0;//计数
while(tmp->next!=nullptr){
tmp=tmp->next;
printf("第%3d 个元素值为 %d\n",++i,tmp->data);
}
}else{
printf("线性表为空。\n");
}
}
int main(){
LinkList L;
// List_HeadInsert(L);
List_TailInsert(L);//创建链表
PrintList(L);
ListInsert(L,2,100);//在第二位插入100
printf("\n");
PrintList(L);
int deleteElem;
ListDelete(L,1,deleteElem);//删除第一位元素
printf("\n");
PrintList(L);
system("pause");
}
运行截图