单链表
单链表思路:
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 ; } } |