如何创建一个单链表.docx
《如何创建一个单链表.docx》由会员分享,可在线阅读,更多相关《如何创建一个单链表.docx(10页珍藏版)》请在冰豆网上搜索。
如何创建一个单链表
1.如何创建一个单链表?
链表节点的定义:
typedefstructnodeintdata;//节点内容node*next;//下一个节点}node;
单链表的创建:
1//创建单链表
2
node*create()
5node*head,*p,*q;
6
创建头节点
intx=0;
7head=(node*)malloc(sizeof(node));//
9while
(1)
10{
11printf("Pleaseinputthedata:
");
12scanf("%d",&x);
13if(x==0)//data
为0时创建结束
14break;
15p=(node*)malloc(sizeof(node));
16p->data=x;
17if(++i==1)
18{//链表只有一个元素
19head->next=p;//连接到head的后面
20}
23q->next=p;//连接到链表尾端25q=p;//q指向末节点
27q->next=NULL;//链表的最后一个指针为NULL28returnhead;
29}
面的代码中,使用while循环每次从终端读入一个整型数据,并调用malloc动态分配链表节点内存存储这个整型数据,然后再插入到单链表的末尾。
最后当数据为0时表示插入数据结束,此时把末尾节点的next指针置为NULL。
2.查找单链表中间元素?
解析:
cur指向当前以扫描链表的尾节
这里使用一个只用一遍扫描的方法。
描述如下:
假设mid指向当前已经扫描的子链表的中间元素,点,那么继续扫描即移动cur到cur->next,这时只需判断一下应不应移动mid到mid->next就行了。
所以一遍扫描就能找到中间位置。
代码如下:
1node*search(node*head)
3inti=0;
4intj=0;
5node*current=NULL;
6node*middle=NULL;
8current=middle=head->next;
9while(current!
=NULL)
10{
11if(i/2>j)
12{
13j++;
14middle=middle->next;
17current=current->next;
21}
3.打印单向链表?
解析:
单链表的打印:
1//打印单链表
2voidprint(node*head)
4node*p;
5
链表为空
intindex=0;
6if(head->next==NULL)//
8printf("Linkisempty!
\n");
9return;
10}
11p=head->next;
12while(p!
=NULL)//遍历链表
13
//打印元素
{
14printf("The%dthnodeis:
%d\n",++index,p->data);
可计算单链表长度count++;
15p=p->next;
16}
17
}
打印各个节点内容,当遇到NULL时结束循环。
4.查找单链表节点?
单链表的查找节点:
1//查找单链表pos位置的节点,返回节点指针
5node*p=head->next;
8printf("incorrectpositiontosearchnode!
\n");
9returnNULL;
10
}
12{
13returnhead;
14}
15if(p==NULL)
16
链表为空
{
17printf("Linkisempty!
\n");//
18returnNULL;
19}20
21while(--pos)
22{
23if((p=p->next)==NULL)
24{//超出链表返回
25printf("incorrectpositiontosearchnode!
\n");
26break;
27}
28}
29returnp;
30}
5.单链表插入节点?
解析:
向单链表中某个位置(第pos个节点)之后插入节点,这里分为插入到链表首部、插入到链表中间,以及链表尾端三种情况:
5node*item=NULL;
8item=(node*)malloc(sizeof(node));
9
item->data=data;
10
11{
13returnhead;
14}
16if(p!
=NULL)
17{
20}
21returnhead;
22}
6.单向链表删除节点?
解析:
单链表删除节点:
1//删除单链表的pos位置的节点,返回链表头指针
2//pos从1开始计算,1表示删除head后的第一个节点
3node*delete_node(node*head,intpos)
5node*item=NULL;
6node*p=head->next;
7if(p==NULL)//链表为空
9printf("linkisempty!
\n");
10returnNULL;
11}
13if(p!
=NULL&&p->next!
=NULL)
15item=p->next;
16p->next=item->next;
17deleteitem;
18}
19returnhead;
20}
7.单向链表的逆序?
解析:
这是一个经常被问到的面试题,也是一个非常基础的问题。
比如一个链表是这样的:
1->2->3->4->5通过逆置后成为5->4->3->2->1。
最容易想到的方法是遍历一遍链表,利用一个辅助指针,存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。
1node*reverse(node*head)
3
链表为空
node*p,*q,*r;
5if(head->next==NULL)//
7returnhead;
11p=head->next;
12
q=p->next;//保存原第二个节点
13
20}
21head->next=p;//新的第一个节点为原末节点
22returnhead;
23}
8.单链表的正向排序?
解析:
面试结构体定义和代码如下:
1typedefstructnode
3intdata;
4node*next;
5}node;
7node*InsertSort(void)
9intdata=0;
10structnode*head=NULL,*New,*Cur,*Pre;
11while
(1)
12{
13printf("pleaseinputthedata\n");
14
scanf("%d",&data);
16{17break;
18}
19New=(structnode*)malloc(sizeof(structnode));
23{//第一次循环时对头节点赋值
26}27if(New->data<=head->data)
28{//head之前插入节点
29New->next=head;
30head=New;
31continue;
32}
33Cur=head;
34
找到需要插入的位置
位置在中间
while(New->data>Cur->data&&//
35Cur->next!
=NULL)
36{
37Pre=Cur;
38Cur=Cur->next;
39}
40if(Cur->data>=New->data)//
41{//把new节点插入到Pre和cur之间
42Pre->next=New;
43New->next=Cur;
44}
45else//位置在末尾
46Cur->next=New;//把new节点插入到cur之后
47}
48returnhead;
49}
9.有序单链表的合并?
已知两个链表head1和head2各自有序,请把它们合并成一个链表依然有序。
使用非递归方法以及递归方法。
解析:
首先介绍非递归方法。
因为两个链表head1和head2都是有序的,所以我们只需要找把较短链表的各个元素有序的插入到较长的链表之中就可以了。
源代码如下:
3node*p=head;
4node*q=NULL;//始终指向p之前的节点
6while(p->datadata&&p!
=NULL)
8q=p;
9p=p->next;
10
}
13{
14item->next=p;
15returnitem;
16}
17//插入到q与p之间之间
18q->next=item;
19item->next=p;
20returnhead;
21}21
22/*两个有序链表进行合并*/23node*merge(node*head1,node*head2)
24{
25node*head;//合并后的头指针26node*p;
27node*nextP;//指向p之后28
33elseif(head2==NULL)
35returnhead1;
36}37
选取较短的链表
38//两个链表都不为空39if(length(head1)>=length(head2))//40{//这样进行的插入次数要少些
41head=head1;
42p=head2;
43}
44else
45{
46head=head2;
47p=head1;
48}49
50while(p!
=NULL)
51{
52nextP=p->next;//
保存p的下一个节点
把p插入到目标链表中
53head=insert_node(head,p);//
54p=nextP;//
指向将要插入的下一个节点
55}
56
57returnhead;
58}
这里insert_node()
函数是有序的插入节点,注意与前面例题中的函数有区别,这
里它传入的参数是
node*类型。
然后在mergeO函数中(代码52~55行)循环把短链
表中的所有节点插入到长链表中。
接下来介绍非递归方法。
比如有下面两个链表:
链表1:
1->3->5
链表2:
2->4->6
递归方法的步骤如下:
1)比较链表1和链表2的第一个节点数据,由于1<2,因此把结果链表头节点指
向链表1中的第一个节点,即数据1所在的节点。
2)对剩余的链表1(3->5)和链表2再调用本过程,比较得到结果链表的第二个节点,即2与3比较得到2。
此时合并后的链表节点为1->2。
接下来的过程类似
(2),如此递归知道两个链表的节点都被加到结果链表中。
1node*MergeRecursive(node*head1,node*head2)
3node*head=NULL;
5if(head1==NULL)
7returnhead2;
9if(head2==NUL)10{
11returnhead1;
12}13
14if(head1->datadata)
15{
16head=head1;
17head->next=MergeRecursive(head1->next,head2);
18}
19else
20{
21head=head2;
22head->next=MergeRecursive(head1,head2->next);
23}24
面是测试程序:
4
创建单链表2
node*head2=create();//
5//node*head=merge(head1,head2);
6node*head=MergeRecursive(head1,head2);
7print(head);
9return0;
10}这里使用merge()函数和MergeRecursive()函数测试,结果一致。