单向链表的实现

链表核心要素:每个节点由数据域和指针域组成,指针域指向下一个节点的内存地址。

代码实现

  定义结构体

 

1
2
3
4
5
6
typedef struct Linknode
{
    int data;//节点的数据域
    Linknode* next;//节点的指针域
 
}_Linknode,Linklist;//数据域,指针域

 

  初始化一个空链表

1
2
3
4
5
6
7
8
9
bool InitList(Linklist* &list)
{
list = new _Linknode;
 
if (!list) return false;
 
list->next = NULL;
return true;
}

  

  前插法

1
2
3
4
5
6
7
8
9
bool Listinsert_front(Linklist* &list, _Linknode* node)
{
if (!list || !node) return false;
 
node->next = list->next;
list->next = node;
 
return true;
}

  

  尾插法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool Listinsert_back(Linklist* &list, _Linknode* node)
{
_Linknode* last = NULL;
if (!list || !node) return false;
 
last = list;
 
while (last->next)last = last->next;
 
node->next = NULL;
last->next = node;
 
return true;
}

  

  指定位置插入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool LinkInsert(Linklist* & list, int i, int& e)
{
if (!list) return false;
 
int j = 0;
Linklist* p, * s;
 
p = list;
 
while (p && j < i - 1)//查找位置为i-1的节点,p指向该节点
{
p = p->next;//每循环一次p向后进一步,指向下一个节点
j++;
}
 
if (!p || j > i - 1) return false;
 
s = new _Linknode;//生成新的节点
s->data = e;
s->next = p->next;
p->next = s;
 
return true;
}

  

  元素获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
bool Link_GetElem(Linklist*& list, int i, int& data)
{
int index;
Linklist* p;
 
if (!list || !list->next) return false;
 
p = list->next;
index = 1;
 
while (p && index < i)//顺链表向后扫描,直到p指向第i个元素或p为空
{
p = p->next;
index++;
}
 
if (!p || index > i) return false;
 
data = p->data;
 
return true;
}

  

  查找元素按值查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool Lonk_FindElim(Linklist*& list, int data)
{
int index;
Linklist* p;
p = list->next;
index = 1;
 
if (!list || !list->next) return false;
 
while (p && p->data != data)
{
p = p->next;
index++;
}
cout << index << endl;
 
if (!p)
{
index = 0;
return false;
}
 
return true;
}

  

  单链表的遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void Linkprint(Linklist* list)
{
_Linknode* p = NULL;
if (!list)
{
cout << "链表为空。" << endl;
return;
}
 
p = list->next;
 
while (p)
{
cout << p->data << "\t";
p = p->next;
}
cout << endl;
}

  

  删除元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool LinkDelete(Linklist*& list, int i)
{
Linklist* p, * q;
int index = 0;
p = list;
 
while ((p->next) && (index < i - 1))//查找第 i-1 个结点,p 指向该结点
{
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;
}

  

  销毁单链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void LinkDestory(Linklist*& list)
{
//定义临时节点p指向头节点
Linklist* p = list;
cout << "销毁链表!" << endl;
 
while (p)
{
list = list->next;//list 指向下一个节点
delete p;
p = list;//p 移向下一个节点
}
 
  return
}

  

  main函数

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
int main(void)
{
Linklist* list = NULL;
_Linknode* s = NULL;
//初始化一个空链表
InitList(list);
 
 
//前插法
for (int i = 0; i < n; i++)
{
s = new _Linknode;
cout << "头部第" << i << "个:";
cin >> s->data;
Lestinsert_front(list, s);
}
Linkprint(list);
 
  
 
//尾插法
std::cout << "请输入元素个数 n:";
cin >> n;
for (int i = 0; i < n; i++)
{
s = new _Linknode;
cout << "尾部第" << i << "个:";
cin >> s->data;
Listinsert_back(list, s);
}
Linkprint(list);
 
  
 
//指定位置插入
for (int i = 0; i < 3; i++)
{
cout << "插入地址:";
cin >> n;
int data = 0;
cout << "参数:";
cin >> data;
LinkInsert(list, n, data);
Linkprint(list);
}
 
  
 
int element;
//获取第二个节点的值
if (Link_GetElem(list, 2, element))
{
cout << "获取成功!" << element << endl;
}
else
{
cout << "获取失败!" << endl;
}
//查找值为2的节点
if (Lonk_FindElim(list, 2))
{
cout << "查找成功" << endl;
}
else
{
cout << "查找失败" << endl;
}
cout << "删除之后" << endl;
LinkDelete(list, 2);//删除
Linkprint(list);//遍历
LinkDestory(list);//销毁
Linkprint(list);//遍历
return 0;
}

 

  

 

编译环境:visual studio 2019

注:如有错误请与我联系,万分感谢!!!

 

posted @   乐吴  阅读(54)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示