链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。下面为其定义,初始化,添加元素,插入元素,删除元素,销毁,打印顺序表的具体代码实现~
单链表算法实现
1.链表的定义
Typedef struct LinkNode
{
int data; //数据域(可以为int,也可以为其他类型)
struct LinkNode *next; //指针域
}LinkList,LinkNode;
2.单链表的初始化
bool InistList(LinkList &L)
{
L=new LinkNode;
if(!L) return false;
L->next=NULL;
return true;
}
3.单链表前插法插入元素
bool ListInsert_front(LinkList* &L,LinkNode*node)
{
if(!L||!node) return false;
node->next=L->next;
L->next=node;
return true;
}
4.单链表尾插法插入元素
bool ListInsert_back(LinkList* &L,LinkNode* node)
{
LinkNode *last=NULL;
if(!L||!node) return false;
last=L;
while(last->next) last=last->next;
node->next=NULL;
last->next=node;
}
5.单链表的遍历
void LinckPrint(LinkList* &L)
{
LinkNode *p=NULL;
if(!L) return false;
p=L->next;
while(p)
{
cout<<p->data<<"\t";
p=p->next;
}
}
6.单链表任意位置的插入
bool LinstInsert(LinkList* &L,int i,int &e)//i为要插入元素位置,e为要插入的元素
{
if(!L) return false;
int j=0;
LinkList *p,*s;
p=L;
While(p&&j<i-1) //遍历到要插入的前一个元素
{
p=p->next;
j++;
}
if(!p||j>i-1) return false;
s=new LinkNode;
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
7.单链表获取元素
bool Link_GetElem(LinkList* &L,int i,int &e) //单链表的取值
{
LinkList *p;
int index;
if(!L||!L->next) return false;
p=L->next;
index=1;
while(p && index<i)
{
p=p->next;
index++;
}
if(!P||index>i) return false;
e=p->data;
return true;
}
8.单链表按值查找元素
bool Link_FindElem(LinkList* L,int e) //按值查找
{
LinkList *p;
p=L->next;
if(!L||!L->next) return false;
while(p&&p->data!=e)
{
p=p->next;
}
if(!p) return false;
return true;
}
9.单链表删除元素
bool LinkDelete(LinkL* &L,int i)
{
LinkList *p,*q;
int index=0;
p=L;
while((p->next)&&(index<i-1))
{
p=p->next;
index++;
}
if(!p->next||(index>i-1)) return false;
q=p->next;
p->next=q->next;
delete q;
return true;
}
10.单链表的销毁
void LinkDestroy(LinList* &L)
{
LinkList *p=L;
while(p)
{
L=L->next;
delete p;
p=L;
}
}
循环链表算法实现(循环链表结构体定义和单链表一样)
1.循环链表初始化
bool InistList(LinkList &L)
{
L=new LinkNode;
if(!L) return false;
L->next=L; //头节点指针域指向自己
L->data=-1; //头节数据域为-1
return true;
}
2.循环链表尾插法插入元素
bool ListInsert_back(LinkList* &L,LinkNode* node)
{
LinkNode *last=NULL;
if(!L||!node) return false;
if(L==L->next) //只有头节点
{
node->next=L;
L->next=node;
}
else
{
last=L->next;
while(last->next!=L) last=last->next; //定位尾节点
node->next=L;
last->next=node;
}
}
3.循环链表的遍历
void LinckPrint(LinkList* &L)
{
LinkNode *p;
if(!L||!L==L->next) return false;
p=L->next;
while(p!=L) //p不等于头结点就一直输出
{
cout<<p->data<<"\t";
p=p->next;
}
}
双向链表
1.双向链表的定义
Typedef struct LinkNode
{
int data; //数据域(可以为int,也可以为其他类型)
struct LinkNode *next; //后指针域
struct LinkNode *prev; //前指针域
}LinkList,LinkNode;
2.双向链表的初始化
bool InistList(LinkList &L)
{
L=new LinkNode;
if(!L) return false;
L->next=NULL;
L->prev=NULL;
L->data=-1;
return true;
}
3.双向链表的前插法
bool ListInsert_front(LinkList* &L,LinkNode*node)
{
if(!L||!node) return false;
if(L->next) L->next->prev=node; //第二个结点的prev指向第一个结点
node->next=L->next
node->prev=L;
L->next=node; //头结点next指向新结点
return true;
}
4.双向链表的尾插法
bool ListInsert_back(LinkList* &L,LinkNode* node)
{
LinkNode *last=NULL;
if(!L||!node) return false;
last=L;
while(last->next) last=last->next;
node->next=NULL;
last->next=node;
node->prev=last;
return true;
}
5.双向链表删除节点
bool LinkDelete(LinkL* &L,int i)
{
LinkList *p;
int index=0;
p=L;
if(!L||!L-next) return false;
while(p && index<i)
{
p=p->next;
index++;
}
if(!p) return false;
p->prev->next=p->next;
p->next->prev=p->prev;
delete p;
return true;
}