目录
链表原理就不过多解释了,直接代码中理解吧
单向链表算法实现
1.数据类型定义
typedef struct _LinkNode
{
int data; //数据
struct _LinkNode* next; //下一节点指针
}LinkNode, LinkList; //两个别名
2.初始化空表
bool InitList(LinkList* &L)
{
L = new LinkNode;
if (!L) return false;
L->next = NULL;
return true;
}
3.前插法
①空链表
②插入第一个节点
③插入第二个节点
具体操作如下图
头结点指向节点2,结点2指向节点1
头结点L指向A1, 这个链接赋值给新节点即可
New->next = L->next
头结点在连上新节点
L->next = New
/*前插法*/
bool ListInsert_front(LinkList* &L, LinkNode* node)
{
if (!L || !node) return false;
node->next = L->next;
L->next = node;
}
4.后插法
理解前插,后插也很简单,只需要定义一个临时节点last,用于遍历到链表的末尾,循环条件是节点next为空,找到最后一个节点后,新节点直接链接即可,后插法要把新节点的next指针置为空,方便下次查找
/*后插法*/
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;
return true;
}
5.任意位置插入数据
在节点2的位置插入方法:
如下图,遍历到插入点, 新节点next替换为原节点next,原节点连接到新节点.
插入节点的方法跟前插类似,多一步找插入位置的过程.
通过代码理解,掌握了前插法,这一步就很简单了
/*指定位置插入*/
bool LinkInsert(LinkList*& L, int i, int& e)//插入位置,插入元素
{
if (!L) return false;
//找到插入位置的前一个节点
int j = 0;
LinkList* tmp, * s;
tmp = L;
while (j < i - 1 && tmp) //查找位置为i-1的节点, tmp指向该节点
{
tmp = tmp->next;
j++;
}
if (!tmp || j > i - 1) //插入的位置不对,大于总节点,或小于0
{
return false;
}
s = new LinkNode; //新节点
s->data = e;
s->next = tmp->next;
tmp->next = s;
return true;
}
6.按值查找数据
/*按值获取元素*/
bool Link_FindElem(LinkList* L, int e) //按值查找
{
//在带头结点的单链表 L 中查找值为 e 的元素LinkList *p;
LinkList* p;
p = L->next;
while (p && p->data != e) { //顺链域向后扫描,直到 p 为空或 p 所指结点的数据域等于 e
p = p->next; //p 指向下一个结点
}
if (!p)return false;
return true;
}
7.删除
/*删除元素*/
bool LinkDelete(LinkList*& L, int i) //单链表的删除
{
//在带头结点的单链表 L 中,删除第 i 个位置
LinkList* p, * q;
int j;
p = L;
j = 0;
while ((p->next) && (j < i - 1)) //查找第 i-1 个结点,p 指向该结点
{
p = p->next;
j++;
}
if (!(p->next) || (j > i - 1))//当 i>n 或 i<1 时,删除位置不合理
return false;
q = p->next; //临时保存被删结点的地址以备释放空间
p->next = q->next; //改变删除结点前驱结点的指针域delete
delete q; //释放被删除结点的空间
return true;
}
8.单链表销毁
/*单链表销毁*/
void LinkDestroy(LinkList* &L)
{
LinkList* tmp = L;
cout << "销毁链表" << endl;
while (tmp)
{
L = L->next;
delete tmp;
tmp = L;
}
}
循环链表算法实现
1.数据类型定义
同单链表
2.初始化空表
bool InitList(LinkList* &L)
{
L = new LinkNode;
if (!L) return;
L->next = L;
L->data = -1;
return true;
}
3.尾插法
①空链表插入
这里注意,代码中判断是否为末尾节点的判定有所更改,原来单链表是判断next是否指向空,现在循环链表判断next是否指向头节点.
②已存在节点插入
遍历找到链表的末尾结点, 将末尾结点的next指针指向新节点,新节点指向头结点(L)
/*尾插法*/
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;
}
return true;
}
双向链表算法实现
后续补充