数据结构
单链表
创建链表
#include<iostream>
using name std;
#define ElemType int
typedef struct Lnode//typedef的作用是给结构体起别名,在这里的作用是 给结构体起分别为Lnode,*LinkList的名字,我们常用Lnode表示结点,用LinkList表示指向Lnode的指针
{
ElemType data;//结点的数据域
struct Lnode *next;//结点的指针域
}Lnode,*LinkList;
链表概念
![链表介绍](https://i-blog.csdnimg.cn/blog_migrate/fb54d8b99e8bfe7616ed6ee6ea107765.png)
创建一个带头节点的单链表
Status ListDelete_L(Linlist &L,int i,ElemType &e)
{
L=new LNode;//开辟新内存
L->next=NULL;//将头节点的指针域制空,就可也得到一个带头结点的空链表
return OK;
}
判断链表是否为空
int ListEmpty(Linklist L)
//若L为空表,则返回1否则返回0
{
if(L->next!=NULL)
return 0;
else return 1;
}
计算表长
Status ListDelete_L(Linlist &L)
/*表长*/
{
Linklist p;//创建新的结点
p=L->next//初始化链表
int i=0;
while(p)//如果p为0,相当于p!=NULL 链表已遍历到尾部 退出循环
{
i++;
p=p->next;
}
}
找相同值返回序号
int LocateELem_L(LinkList L,Elemtype e)
//在线性表L中查找值为e的数据元素的位置序号
{
LinkList p=->next;
int i=1;
for(p&&p->data!=e)
{
i++;
p=p->next;
}
if(p!=NULL)return i;
else return 0;
}
插入元素
![插入一个元素](https://i-blog.csdnimg.cn/blog_migrate/d4e8b1201e7eae11b8d1e4e2ffa189c9.png)
Status ListDelete_L(Linlist &L,int i,ElemType e)
//在L中第i个元素之前插入数据元素x
{
Linlist p=L;//新建立一个结点p
j=0;
while(p&&j<i-1)//找到第i-1个元素
{
j++;
p=p->next;
}
if(!p||j>i-1)return ERROR;//判断i是否存在
Linlist s=new Lnode;//创建一个新结点s
s->data=x;
s->next=p->next;//1
p->next=s;//2
//注意1和2不可颠倒,颠倒会导致第i+1个元素的地址丢失
}
找相同值
Lnode*LocateELem_L(LinkList L,Elemtype e)
//在线性表L中查找值为e的数据元素
//找到返回e的地址找不到返回NULL
{
LinkList p=L->next;
while(p&&p->data==e)
p=p->next;
return p;
}
头插法
![头插法](https://i-blog.csdnimg.cn/blog_migrate/24e05c725a0cabd1b57f9acd08b273bf.png)
/*头插法*/
void createlist_h(linklist&L,int n)
{
L=new Lnode;
L->next=NULL;//先建立一个带头节点的单链表
for(int i=0;i<n;i++)
{
p=new Lnode;//生产新节点
cin>>p->data;//输入要插入的值
p->next=L->next;//插入表头
L->next=p;
}
}
尾插法
![尾插法](https://i-blog.csdnimg.cn/blog_migrate/48e7897a3daa326a4242b758f8d9573b.png)
//正位序输入n个元素的值,建立带表头结点的单链表L
void creatlist_R(LinkList&L,int n)
{
L=new Lnode;//建立一个新链表
L->next=NULL;
LinkList r=new Lnode;//新建一个尾指针
r=L;
for(int i=0;i<n;i++)
{
LinkList p=new Lnode;
cin>>p->data;//生成新结点,并赋值
p->next=NULL;//将尾部制空
r->next=p;//插入到表尾
r=p;//r指向新的p尾节点
}
循环链表
![循环链表](https://i-blog.csdnimg.cn/blog_migrate/8558538613275c47d5501698bdd4f6c2.jpeg)
带尾指针的循环链表合并
原理如下:
![带尾指针的循环链表合并](https://i-blog.csdnimg.cn/blog_migrate/ed65bec64d408502ae0007aaecb50273.png)
LinkList connect(LinkList Ta,LinkList Tb)
{
Lnode *p=new Lnode;
Lnode *p=Ta->next;//保存Ta头指针
Ta->next=Tb->next->next;//Ta尾指针指向Tb首元节点
delete Tb->next;//释放Tb头节点内存
Tb->next=p;//将Tb尾指针指向Ta头结点重新构成循环链表
}
双向链表
![双向链表](https://i-blog.csdnimg.cn/blog_migrate/e7f5f48e67060c18aea9352b9edd9af3.png)
//作者:余双
#include<iostream>
#include<string>
using namespace std;
#define Elemtype int
typedef struct DuLNode
{
Elemtype data;
struct DuLNode *prior,*next;
}DuLNode,*DuLinkList;
//双向链表结构的对称性:
// p->prior->next=p=p->next->prior
//双向表在插入和删除需要同时修改两个方向上的指针------重点!!!!
int main()
{
system("pause");
return 0;
}
双向链表的插入
![双向链表的插入](https://i-blog.csdnimg.cn/blog_migrate/af174a133ba823d365aaa3173f6e6b11.jpeg)
void Listlnsert_Dul(DuLinkList&L,int i,ElemType e)
//在带头结点的双向循环链表L中第i个位置之前插入元素e
{
DuLinkList *p=new DuLnode;
p=L;
int j=0;
while(p&&j<i)
{
j++;
p=p->next;
}
if(!p||j>i)exit(0);
DuLinkList *s=new DuLnode;
s->data=e;
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prior=s;
}
双向链表的删除
![双向链表的删除](https://i-blog.csdnimg.cn/blog_migrate/e016089c227222d031d9e4aec4a7f1be.png)
void Listlnsert_Dul(DuLinkList&L,int i,ElemType e)
//在带头结点的双向循环链表L中第i个位置之前插入元素e
{
DuLnode *p=new DuLnode;
p=L;
int j=0;
while(p&&j<i)
{
j++;
p=p->next;
}
if(!p||j>i)exit(0);
p->data=e;
p->prior->next=p->next;
p->next->prior=p->prior;
}