一 、单向链表:
单向链表是一种特殊的数组,它的每个元素称为节点,每个节点包括两个部分:数据域(存放数据)、指针域(存放下一个节点的地址)
-
单向链表的结构:
-
特点:
链表比数组多了指针域,链表通过上一节点的指针域找下一个数据,如上图所示,它的存储空间不一定连续。
-
实现:
//----------------单向链表存储结构-------------------
typedef struct LNode
{
ElemType data; //Data是一个变量,存放结点中的数据
struct LNode *next; //*next是指针域,指向结点的下一个结点
}LNode,*LinkList;
假设L是LinkList型的变量,则L为单链表的头指针,它指向表中第一个节点,若L为空,则所表示的线性表为空表,其长度为0.也可以在单链表中的第一个节点之前附设一个节点,称之为头结点。头结点的数据域可以不存储任何信息,也可以存储线性表的长度等等此类的信息。头结点的指针域存储指向第一个节点的指针(即第一个元素结点的存储位置)。
在单链表中,任何两个的存储位置之间没有固定的联系。然而每个元素的存储位置都包含在其直接前驱节点的信息之中。假设p是指向线性表中第i个数据元素(节点ai)的指针,则p -> next是指向第 i+1 个数据元素(节点ai+1)的指针。即:p -> data=ai;则p -> next -> data = ai+1。
GetElem函数:
Status GetElem(LinkList L,ElemType &e)
{
p = L->next; //L为带头结点的单链表的头指针
j = 1;
while(p && j < i) //当第i个元素存在时,将其值赋给e并返回OK,否则返回ERROR
{
p = p->next;
++j;
}
if(!p || j > i)
{
return ERROR;
}
e = p->data;
return OK;
}
//--------------------插入----------------------
要插入元素E,首先要生成一个数据域为E的节点,然后插入;插入的过程中要改变指针的指向,只要令E的前驱的指针域指向E然后令E的指针域指向本来E前驱的后继的数据域,这样就插入了一个新元素。即:假设s为指向节点E的指针,s->next = p->next; p -> next = s;
在链表中插入结点是时,则需要考虑下面几点情况:
(1) 插入前链表是一个空表,直接插入。
(2) 若插入的是链表第一个节点后,则插入后,该结点为第一个结点。
(3) 若不是第一个结点,则首先要找出该节点的上一个结点,然后按以上插入元素E操作。
代码实现如下:
Status ListInster(Link &L,int i,ElemType e) //在第i个位置之前插入e
{
p = L;
j = 0;
while(p && j < i - 1)
{
p = p -> next;
++j;
}
if(!p || j > i-1)
{
return ERROR;
}
s = (LinkList)mallon(sizeof(LNode)); //生成新结点
s -> data = e;
s -> next = p->next;
p->next = s;
return OK;
}
//-----------------------删除---------------------
与插入思路相同,只是改变节点指向,令要删除的元素的前驱的指针指向要删除元素的后继的数据域。(当然,也要考虑如插入类似的情况)
即: p -> next = p -> next ->next;
代码如下:
Status ListDelete(LinkList &L,ElemType &e)
{
p = L;
j = 0;
while(p -> next && j < i-1)
{
p = p->next;
++j;
}
if(!(p->next) || j > i-1)
{
return ERROR;
}
q = q->next;
p -> next =q -> next;
e = q->next;
free(q);
return OK;
}
以下为整体代码:
-----------head.h ---------
#ifndef List
#include<iostream>
using namespace std;
typedef int ElemType;
typedef struct LNode
{
ElemType data;
LNode *next;
};
class LINK_LIST
{
public:
LINK_LIST();
~LINK_LIST();
bool InitList();
bool LlistInster(ElemType elem,ElemType pos);
bool ListDelete(ElemType pos);
void output();
private:
LNode *head;
};
#endif // !List
---------------fun.cpp---------------
#include"head.h"
LINK_LIST::LINK_LIST() //初始化
{
head = new LNode;
head->next = NULL;
}
LINK_LIST::~LINK_LIST() //清空链表
{
LNode *p;
while (head->next)
{
p = head->next;
head->next = p->next;
delete p;
}
}
bool LINK_LIST::InitList()
{
LNode *p,*temp;
p = head;
ElemType num,i = 1;
cout << "请输入要输入的元素个数:";
cin >> num;
cout << "现在输入元素吧!" << endl;
while (i <= num)
{
temp = new LNode;
cin >> temp->data;
temp->next = p->next;
p->next = temp;
i++;
}
return true;
}
bool LINK_LIST::LlistInster(ElemType elem, ElemType pos)
{
LNode *p,*s;
ElemType n;
n = 0;
p = head;
while (p && n < pos - 1)
{
p = p->next;
++n;
}
if (!p || n > pos - 1)
{
return false;
}
s = new LNode;
s->data = elem;
s->next = p->next;
p->next = s;
return true;
}
bool LINK_LIST::ListDelete(ElemType pos)
{
LNode *p,*q;
p = head;
int n = 0;
while (p && n < pos - 1)
{
p = p->next;
++n;
}
if (!p || n > pos - 1)
{
return false;
}
p->next = p->next->next;
return true;
}
void LINK_LIST::output()
{
LNode *p;
p = head->next;
while (p != NULL)
{
cout << p->data<<" ";
p = p->next;
}
cout << endl;
}
-----------------main.cpp-------------------
#include"head.h"
int main()
{
LINK_LIST list;
ElemType type,pos;
list.InitList();
list.output();
cout << "请输入要插入的元素以及位置:";
cin >> type >> pos;
list.LlistInster(type,pos);
list.output();
cout << "请输入删除元素位置:";
cin >> pos;
list.ListDelete(pos);
list.output();
system("pause");
return 0;
}
前半部分部分采用C语言是为了便于理解,后部整体代码为C++就很容易理解了。
以上代码测试环境为VS2017