本贴继续记录数据结构-线性表的学习代码
PS:根据网络课程自学,使用c/c++语言混合编写,但大量代码还是以c为主。部分代码区分带头节点与不带头结点。
链表
目录
目录
目录
1.包含头文件
#include <iostream>
#include <stdbool.h>
using namespace std;
2.定义节点
//定义单链表节点类型
typedef struct LNode
{
int data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList; //LNode强调结点,LinkList强调链表
3.判空
//判空
bool Empty(LinkList L)
{
//[不带头] return (L==NULL);
if(L->next == NULL) //[带头]
return true;
else
return false;
}
4.求表长
//求表长
int Length(LinkList L)
{
int len=0; //计数变量
LNode *p=L;
while (p->next != NULL) //判断下一个结点是否为空
{
p=p->next;
len++; //每访问一个结点,自增1
}
return len; //返回结点数量
}
5.按序号插入
PS:部分代码涉及封装操作,即将原本复杂、重复的代码写成一个函数,并调用。
//按序号插入 在第i个位置插入元素e(带头结点)
bool ListInsert(LinkList& L, int i, int e)
{
if(i<1) //判断结点是否合法(位序从1开始
return false;
//(可封装)LNode *p = GetElem(L,i-1);
LNode *p; //指针p指向当前能扫描到的结点
int j=0; //当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点
while (p != NULL && j < i - 1) //在第i个结点前插入所以循环到i-1个结点
{
p=p->next;
j++;
}
//以下代码可用 (封装)后插函数代替
//return InsetNextNode(p,e);
if(p==NULL) //i值不合法,大于当前链表长度
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));//动态分配一个地址
s->data=e; //元素e插入到数据区
s->next=p->next; //指针指向原结点的下一结点
p->next=s; //原结点指针指向插入结点s
return true; //插入成功
}
//按序号插入 在第i个位置插入元素e(不带头结点)
bool ListInsert2(LinkList& LL, int i, int e)
{
if(i<1) //判断位序的合法性
return false;
//(可封装)LNode *p = GetElem(L,i-1);
if (i == 1) //插入在第一个结点时
{
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next = LL; //新结点指向原链表
LL=s; //头指针指向新结点
}
//其余操作相同
LNode* p; //指针p指向当前能扫描到的结点
int j = 0; //当前p指向的是第几个结点
p = LL; //L指向头结点,头结点是第0个结点
while (p != NULL && j < i - 1) //在第i个结点前插入所以循环到i-1个结点
{
p = p->next;
j++;
}
//以下代码可用 (封装)后插函数代替
//return InsetNextNode(p,e);
if (p == NULL) //i值不合法,大于当前链表长度
return false;
LNode* s = (LNode*)malloc(sizeof(LNode));//动态分配一个地址
s->data = e; //元素e插入到数据区
s->next = p->next; //指针指向原结点的下一结点
p->next = s; //原结点指针指向插入结点s
return true; //插入成功
}
6.后插操作
//后插操作:在p结点后插入元素e
bool InsertNextNode(LNode* p, int e)
{
if(p==NULL) //判断插入结点是否合法
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
if(s==NULL) //内存分配失败
return false;
s->data=e; //用结点s保存数据元素e
s->next=p->next;
p->next=s; //将结点s连到p之后
return true;
}
7.后插操作
//前插操作:在p结点之前插入元素e
bool InserPriorNode(LNode* p, int e)
{
if(p == NULL) //判断结点是否合法
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
if(s==NULL) //判断内存分配
return false;
s->next=p->next; //将新结点指向下一结点
p->next=s; //将原结点指向新结点
s->data=p->data; //将原结点数据复制到新结点
p->data=e; //将插入数据赋值给原结点
return true;
}
8.按序号、按值查找
//按序号查找(带头),返回第i个元素
LNode* GetElem(LinkList L, int i)
{
if(i<0)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的第几个结点
p=L; //L指向头结点,头结点是第0个结点(不存数据)
while (p != NULL && j < i) //循环到第i个结点
{
p=p->next;
j++;
}
return p;
}
//按值查找(带头),找到数据域==e的结点
LNode * LocateElem(LinkList L, int e)
{
LNode *p = L->next; //从第1个结点开始查找数据域为e的结点
while(p == NULL && p->data != e)
p->next;
return p; //找到后返回该结点指针,否则返回NULL
}
9.按位删除
//按位删除节点(带头
bool ListDelete(LinkList& L, int i, int &e)//用e待会数据
{
if(i<1) //判断位序合理
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点
while (p != NULL && j < i - 1) //循环找到i-1个结点
{
p=p->next;
j++;
}
if(p==NULL) //i值不合法
return false;
if(p->next == NULL) //第i-1个结点后没有其他结点
return false;
LNode *q=p->next; //令q指向被删除结点
e = p->data; //用e返回元素的值
p->next=q->next; //将*q结点从链中“断开”
free(q); //释放结点存储空间
return true; //删除成功
}
10.删除指定结节点
//删除指定结点
bool DeleteNode(LNode* p)
{
if(p == NULL) //判断结点是否为空
return false;
LNode *q = p->next; //令p指向*p的后继结点
p->data = p->next->data; //和后继结点交换数据域
p->next=q->next; //将*q结点从链中断开
free(q); //释放后继结点的存储空间
return true;
}
11. 尾插法、头插法建立单链表
//尾插法建立单链表
LinkList List_Tailnsert(LinkList &L) //正向建立链表
{
int x; //假设输入的数据为整型参数
L=(LNode *)malloc(sizeof(LNode)); //建立头结点
LNode *s,*r=L; //r为表尾结点
cout << "向链表输入值,输入000结束";
cin >> x; //输入结点的值
while (x != 000) //循环插入数据,到000结束
{
s=(LNode *)malloc(sizeof(LNode)); //建立结点,并让s指向这个结点
s->data = x; //插入数据x
r->next = s; //让r指向s,建立链接
r = s; //让r指向新的表尾结点
cin >> x; //输入数据
}
r->next = NULL; //尾结点指针置空
return L;
}
//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)
{
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode)); //创建头结点
L->next = NULL;
cout << "向链表输入值,输入000结束"; //初始为空链表
cin >> x; //插入结点的值
while (x != 000) //输入000结束
{
s=(LNode *)malloc(sizeof(LNode)); //创建新结点,
s->data=x; //x的值插入新结点
s->next=L->next; //新结点直指向L的下一结点
L->next=s; //将新结点插入表中,L为头指针
cin >> x; //再插入数据
}
return L;
}