单链表思路:
1、表示结点,一个数据域,一个链接域,可以采用结构体或者类表示,这里
使用结构体表示。为简单起见,数据类型设置为int。
2、用类表示单链表这个抽象数据类型,包含数据和操作。
1)由于需要一个起始的链表头来开始建立链表,则需声明一个保护类型的指针。
2)建立一个类之后首先需要设定类的构造函数和析构函数。
3)然后是建立单链表,输出单链表。
4)插入、删除结点。
5)辅助函数:判断是否为空链表的函数;定位到给定的索引处。
单链表的结点用结构体来表示:
1
2
3
4
5
|
struct
LinkNode
{
int
data;
//数据域
LinkNode *link;
//结点本身的链接域
};
|
单链表的抽象数据类型用类表示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class
LinkList
{
private
:
LinkNode *head;
//链表头指针,位置不可以改变,建立该链表的时候确定
public
:
LinkList(){}
//构造函数
~LinkList();
//析构函数
/*----------------建立、输出单链表--------------*/
void
InitLinkList();
//建立单链表
void
OutputLinkList();
//输出单链表
/*----------------插入、删除结点-------------*/
bool
InsertNode(
int
data,
int
index);
//插入结点
bool
DeleteNode(
int
index);
//删除结点
};
|
下面介绍单链表的几种关键算法,单链表的建立,输出,插入结点和删除结点:
建立单链表的算法:
1、输入一个值,然后将该值赋值给当前结点的数据域。
2、拉链:head不能改变,所以需要另外声明一个指针*last。
1)将该值赋值给这个新建结点指针的数据域。
2)采用后插法建立单链表
3、将链表指针的最后一个链接域赋值为NULL,容易忽略 head->link=NULL
编程经验:
1、在分配一个存储空间后,加上测试语句是好的编程实践
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
|
void
LinkList::InitLinkList()
{
int
data;
//输入的结点值,以999号结束
cout<<
"请输入单链表的结点值:"
<<endl;
cin>>data;
LinkNode *last;
//head指针不可以改变位置
head=
new
LinkNode;
//链表头指针,要在这里进行初始化,重要,链表的头指针不能改变
if
(head==NULL){cerr<<
"分配错误!"
<<endl;}
last=head;
while
(data!=999)
//如果该值不为999,则拉链,不断重复该过程
{
LinkNode* NewNode=
new
LinkNode;
//新建一个结点,用于拉链
if
(NewNode==NULL){cerr<<
"分配错误!"
<<endl;}
NewNode->data=data;
//附加头结点
//NewNode=head->link;
//head=NewNode; //这两句是典型的错误
last->link=NewNode;
last=NewNode;
//这样也不行
cin>>data;
//输入改值
}
last->link=NULL;
}
|
输出单链表算法:
1、根据链表头指针,输出该链表指针所指向的数据域。
2、判断该指针是否为空,不为空,则向下推进一个。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
void
LinkList::OutputLinkList()
{
LinkNode *current=head->link;
//带附加头结点的链表
if
(current==NULL){cerr<<
"分配错误!"
<<endl;}
cout<<
"单链表为:"
<<endl;
while
(current!=NULL)
{
cout<<current->data<<
" "
;
current=current->link;
//向下推进一个位置
}
cout<<endl;
}
|
插入结点算法:
1、在index位置插入元素,需要先找到第index个元素的位置。
2、插入该元素到index位置,可能出现的情况:
1)先定义一个插入的结点指针*current。
2)声明一个num,用来记录当前的位置和所给的index进行比较。
3)判断num是否等于所给的index值,如果等于,就进行结点的插入操作。
a)需要注意的是current要在index-1的位置。
b)如果不相等,则current位置推进一个位置。
c)最后判断如果num<index 则表明链表太短,这样的操作属于非法操作。
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
|
bool
LinkList::InsertNode(
int
data,
int
index)
{
int
num=0;
//用来记录当前的位置
LinkNode *current=head;
//辅助结点,必须进行初始化
LinkNode *newNode=
new
LinkNode;
//待插入结点
newNode->data=data;
//将该值赋值给该结点值
while
(current!=NULL)
{
num++;
//由于带附加头结点,所以num先要加1,表示第一个结点
if
(index==num)
{
newNode->link=current->link;
current->link=newNode;
//这两句进行结点的插入操作
}
else
{
current=current->link;
//推进一个位置
}
}
if
(num<index)
{
cout<<
"单链表长度太短"
<<endl;
return
false
;
}
else
{
return
true
;
}
}
/*-----------------------------------------*/
|
单链表删除算法:
1、删除给的索引处的结点。
2、需要定义个current指针和一个计数器num;
3、如果num等于给定的index,则需要声明另外一个表示要删除的结点的指针。
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
|
bool
LinkList::DeleteNode(
int
index)
{
LinkNode *current=head;
//循环指针
int
num=0;
while
(current!=NULL)
{
num++;
//由于带附加头结点,所以需要先将num加1
if
(index==num)
{
LinkNode *p=current->link;
//待删除的结点
current->link=p->link;
delete
p;
}
else
{
current=current->link;
}
}
if
(index>num)
{
cout<<
"单链表的长度太短"
<<endl;
return
false
;
}
else
{
return
true
;
}
}
|