分享一下我的bug:
下面会有具体代码, 先留个悬念:
没有bug
//前插法
bool ListInsert_front(LinkList*& L, LinkNode* node)
{
if (!L || !node) return false;
node->next = L->next;
L->next = node;
return true;
}
有bug;
//前插法
bool ListInsert_front(LinkList*& L, LinkNode* node)
{
if (!L || !node) return false;
L->next = node;
node->next = L->next;
return true;
}
只要我把顺序换一下打印就会, 出bug, 你们知道为什么吗?
正确的:
node->next = L->next;
L->next = node;
顺序乱的话:
L->next = node;
node->next = L->next;
现实:
链表的算法实现:
单链表的概念
链表的节点均单向指向下一个节点,形成一条单向访问的数据链
单链表的初始化
typedef struct _LinkNode {
int data; //结点的数据域
struct _LinkNode *next; //结点的指针域
}LinkNode, LinkList; //链表节点、链表
bool InitList(LinkList* &L)//构造一个空的单链表 L
{
L=new LinkNode; //生成新结点作为头结点,用头指针 L 指向头结点
if(!L)return false; //生成结点失败
L->next=NULL; //头结点的指针域置空
return true;
}
单链表增加元素
前插法
//前插法
bool ListInsert_front(LinkList* &L, LinkNode * node){
if(!L || !node ) return false;
node->next = L->next;
L->next = node;
return true;
}
尾插法
//尾插法
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;
}
任意位置插入
//任意位置插法
bool LinkInsert(LinkList* &L, int i, int &e)//单链表的插入
{
//在带头结点的单链表 L 中第 i 个位置插入值为 e 的新结点
int j;
LinkList *p, *s;
p=L;
j=0;
while (p&&j<i-1) //查找第 i-1 个结点,p 指向该结点
{
p=p->next;
j++;
}
if (!p || j>i-1){//i>n+1 或者 i<1
return false;
}
s=new LinkNode; //生成新结点
s->data=e; //将新结点的数据域置为 e
s->next=p->next; //将新结点的指针域指向结点 ai
p->next=s; //将结点 p 的指针域指向结点 s
return true;
}
单链表的遍历
void LinkPrint(LinkList* &L) //单链表的输出
{
LinkNode* p;
p=L->next;
while (p)
{
cout <<p->data <<"\t";
p=p->next;
}
cout<<endl;
}
单链表获取元素
bool Link_GetElem(LinkList* &L, int i, int &e)//单链表的取值
{
//在带头结点的单链表 L 中查找第 i 个元素
//用 e 记录 L 中第 i 个数据元素的值
int j;
LinkList* p;
p=L->next;//p 指向第一个结点,
j=1; //j 为计数器
while (j<i && p) //顺链域向后扫描,直到 p 指向第 i 个元素或 p 为空
{
p=p->next; //p 指向下一个结点
j++; //计数器 j 相应加 1
}
if (!p || j>i){
return false; //i 值不合法 i>n 或 i<=0
}
e=p->data; //取第 i 个结点的数据域
return true;
}
单链表查找元素
bool Link_FindElem(LinkList *L, int e) //按值查找
{
//在带头结点的单链表 L 中查找值为 e 的元素
LinkList *p;
p=L->next;
while (p && p->data!=e){//顺链域向后扫描,直到 p 为空或 p 所指结点的 数据域等于 e
p=p->next; //p 指向下一个结点
}
if(!p)return false; //查找失败 p 为 NULL
return true;
}
单链表删除元素
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 q; //释放被删除结点的空间
return true;
}
单链表销毁
void LinkDestroy(LinkList* &L) //单链表的销毁
{
//定义临时节点 p 指向头节点
LinkList *p = L;
cout<<"销毁链表!"<<endl;
while(p)
{
L=L->next; //L 指向下一个节点
cout<<"删除元素: "<<p->data<<endl;
delete p; //删除当前节点
p=L; //p 移向下一个节点
}
}
具体代码:
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
//数据结构
typedef struct _LinkNode
{
int data;
struct _LinkNode* next;
}LinkNode, LinkList;
//初始化
bool InitList(LinkList*& L)
{
L = new LinkNode;
if (!L) return false;
L->next = NULL;
L->data = -1;
return true;
}
//前插法
bool ListInsert_front(LinkList*& L, LinkNode* node)
{
if (!L || !node) return false;
node->next = L->next;
L->next = node;
return true;
}
//尾插法
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;
}
//指定位置插入
bool LinkInsert(LinkList*& L, int i, int& e)
{
if (!L) return false;
int j = 0;
LinkList* p, * s;
p = L;
while (p && j < i - 1) //查找位置为i-1的节点, p指向该结点
{
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;
}
//打印
void LinkPrint(LinkList*& L)
{
LinkNode* p = NULL;
if (!L)
{
cout << "链表为空." << endl;
return;
}
p = L->next;
while (p)
{
cout << p->data << "\t";
p = p->next;
}
cout << endl;
}
//单链表的取值
bool Link_GetElem(LinkList*& L, int i, int& e) //单链表的取值
{
//在带头结点的单链表L中查找第i个元素
//用e记录L中第i个数据元素的值
int index;
LinkList* p;
if (!L || !L->next) return false;
p = L->next;
index = 1;
while (p && index < i) //顺序表向后扫描, 直到p指向第i个元素或p为空
{
p = p->next; //p指向下一个结点
index++; //计数器index相应加1
}
if (!p || index > i)
{
return false; //i值不合法, i>n 或 i <= 0
}
e = p->data;
return true;
}
//按值查找
bool Link_FindElem(LinkList* L, int e, int& index)
{
//在带头结点的单链表L中查找值为e的元素
LinkList* p = NULL;
p = L->next;
index = 1;
if (!L || !L->next)
{
index = 0;
return false;
}
while (p && p->data != e)
{
p = p->next;
index++;
}
if (!p)
{
index = 0;
return false; //查无此值
}
return true;
}
//单链表的删除
bool LinkDelete(LinkList*& L, int i)
{
LinkList* p, * q;
int index = 0;
p = L;
if (!L || !L->next)
{
return false;
}
while ((p->next) && (index < i - 1))
{
p = p->next;
index++;
}
if (!p->next || (index > i - 1)) //当 i>n 或 i<1 时, 删除位置不合理
{
return false;
}
q = p->next; //临时保存被删结点的地址以备释放空间
p->next = q->next; //改变删除结点前驱结点的指针域
delete q; //释放被删除结点的空间
return true;
}
//单链表的销毁
void LinkDestroy(LinkList*& L)
{
//定义临时节点 p 指向头节点
LinkList* p = L;
cout << "销毁链表!" << endl;
while (p)
{
L = L->next; //L指向下一个结点
cout << "删除元素: " << p->data << endl;
delete p; //删除当前节点
p = L; //p 移向下一个节点
}
}
int main()
{
LinkList* L = NULL;
LinkNode* s = NULL;
//1. 初始化一个空的链表
InitList(L);
//2. 使用前插法插入数据
int n;
cout << "前插法创建单链表" << endl;
cout << "请输入要插入的元素个数: ";
cin >> n;
cout << "\n请依次输入n个元素: " << endl;
while (n > 0)
{
s = new LinkNode; //生成新节点 s
cin >> s->data;
if (ListInsert_front(L, s))
{
cout << "插入成功" << endl;
}
else
{
cout << "插入失败" << endl;
}
n--;
}
LinkPrint(L);
//3. 使用尾插法插入数据
int m = 0;
cout << "尾插法创建单链表" << endl;
cout << "请输入要插入元素个数: ";
cin >> m;
cout << "\n请依次输入 " << m << " 个元素: " << endl;
while (m > 0)
{
s = new LinkNode; //生成新节点 s
cin >> s->data;
if (ListInsert_back(L, s))
{
cout << "插入成功" << endl;
}
else
{
cout << "插入失败" << endl;
}
m--;
}
LinkPrint(L);
//5. 任意位置插入元素
for (int j = 0; j < 2; j++)
{
int i = 0;
int x = 0;
cout << "请输入要插入的位置: ";
cin >> i;
cout << "请输入要插入的元素: ";
cin >> x;
if (LinkInsert(L, i, x))
{
cout << "插入成功.\n\n";
}
else
{
cout << "插入失败.\n\n";
}
LinkPrint(L);
}
//6. 单链表根据位置获取元素
int element = 0;
if (Link_GetElem(L, 2, element))
{
cout << "获取第 2 个元素成功, 值: " << element << endl;
}
else
{
cout << "获取第 2 个元素失败." << endl;
}
//7. 单链表根据值查询元素所在的位置
int index = 0;
if (Link_FindElem(L, 10, index))
{
cout << "查找元素 10 存在, 所在位置: " << index << endl;
}
else
{
cout << "不存在元素 10." << endl;
}
//8. 单链表删除元素
if (LinkDelete(L, 2))
{
cout << "删除的 2 个元素成功" << endl;
}
else
{
cout << "删除第 2 个元素失败" << endl;
}
//9. 销毁单链表
LinkDestroy(L);
system("pause");
return 0;
}
结语:
学到的知识要, 多复习, 多总结, 多敲. 自己写不出来的永远是别人的
分享一下我的技巧: 代数法把具体的数字带进去, 看看能能能找到规律.
还有就是画图, 也很重要.
我是小白, 如果存在问题, 欢迎大神给予评判指正.
错了不可怕, 可怕的是找不出bug
青春励志: 在最美的年龄, 为最纯的梦想, 进最大的努力!