-
链表:
别名链式存储结构或单链表,用于存储逻辑关系为 “一对一” 的数据。与顺序表不同,链表不限制数据的物理存储状态。
顺序表通过连续的地址建立元素之间前后连接关系,链表通过指针方式建立元素之间前后连接关系。
-
链表的缺点:
添加和删除 *** 作需要移动元素。
当数据量特别大的情况,可能没有连续的内存可使用。
用法与顺序表相似,只是适用场景有所不同。
-
链表中由以下两部分组成:
1、数据元素本身,其所在的区域称为数据域;
2、指向直接后继元素的指针,所在的区域称为指针域; -
存储特点:
1、使用链表存储的数据元素,其物理存储位置是随机的。
2、数据元素随机存储,并通过指针表示数据之间逻辑关系的存储结构就是链式存储结构。
3、单链表与字符串有很多相似之处:单链表的结尾为NULL
,字符串的结尾为
。- 实例:
所以,二者处理有许多相似之处。
创建链表、插入(头插和尾插)链表、查找、删除链表、销毁链表
- #
include#
include#
includetypedef
int ; Elementtypedef
struct Node ;{
Element estruct
Node *; next}
;Node*
NodeInputList ()*{
Node= header NULL ;for
(;;);{
Element eint
= num scanf ("%d",&)e;if
(EOF== ) numbreak ;*
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next NULL ;if
(NULL== ) header={
header ; node}
else*{
Node= n ; headerwhile
(!=n->next NULL )={
n ; n->next}
=
n->next ; node}
}
clearerr
(stdin);// 清除EOF状态 return
; header}
void
ShowList (*Node*) header*{
Node= node * ;headerwhile
(!=node NULL )printf{
("%d ",)node->e;=
node ; node->next}
printf
("\n");}
void
SearchList (*Node*) headerprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;*
Node= p * ;headerfor
(int= i 0 ;<i ; index++)i={
p ; p->next}
printf
("下标%d的值为%d\n",,index)p->e;}
void
prepend (*Node*, header)Element e*{
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next * ;header*
=header ; node}
void
InsertList (*Node*) headerprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;;
Element eprintf
("请输入插入值:");scanf
("%d",&)e;if
(0== || index NULL == * )headerprepend{
(,header)e;return
;}
*
Node= p * ;headerfor
(int= i 0 ;<i - index1;++)i={
p ; p->nextif
(NULL== ) pprintf{
("下标输入错误\n");return
;}
}
*
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next ; p->next=
p->next ; node}
int
getsize (*Node) headerint{
= size 0 ;*
Node= p ; headerwhile
(NULL!= ) p={
p ; p->next++
;size}
return
; size}
bool
delete (*Node*, headerint) indexif{
(NULL== * )headerreturn false ;if
(<index 0 )return false ;if
(getsizeindex >= (*)header)return false ;*
Node= p * ;headerif
(0== ) index*{
=header ; p->nextfree
()p;return
true ;}
for
// 查找插入位置的前一个节点。
index-1
(int= i0;<i-index1;++)i={
p; p->next}
*
Node= del ; p->next=
p->next ; del->nextfree
()del;return
true ;}
void
DeleteList (*Node*) headerprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;bool
= res delete (,header)index;if
()resprintf ("删除成功\n");else
printf ("删除失败\n");}
void
Destory (*Node*) header*{
Node= p * ;headerwhile
(NULL!= ) p*{
Node= tmp ; p->nextfree
()p;=
p ; tmp}
*
=header NULL ;}
int
main ()*{
Node= header InputList ();typedef
void ( *)func_t(*Node*) header;struct
char{
*; name;
func_t func}
[ items]= "查看链表" {
{,}ShowList,"下标查找"
{,}SearchList,"插入数据"
{,}InsertList,"下标删除"
{,}DeleteList,}
;const
int = size sizeof ()items/sizeof([items0]);for
(;;)printf{
("选项:\n");for
(int= i 0 ;<i ; size++)iprintf{
("%d.%s\n",+i1,[items]i.)name;}
printf
("0.退出\n");printf
("请输入选项:\n");int
; numscanf
("%d",&)num;if
(0== ) numbreak ;if
(<num 0 || ) num > sizeprintf{
("输入错误,请重新输入\n");continue
;}
[
items-num1].func(&)header;}
Destory
(&)header;}
O(n)
2.4 链表优化
每次获取链表元素个数都要整个遍历一遍,时间复杂度为List
。
在int size
中添加成员O(1)
;记录链表元素个数,时间复杂度降为main.c
。
注意初始化、添加和删除元素函数都需要添加相应处理
- #
include#
include"list2.h" int
main ()*{
List= list CreateList ();typedef
void ( *)func_t(*List) list;struct
char{
*; name;
func_t func}
[ items]= "查看链表" {
{,}ShowList,"下标查找"
{,}SearchList,"插入数据"
{,}InsertList,"下标删除"
{,}DeleteList,"下标修改"
{,}EditList,}
;const
int = size sizeof ()items/sizeof([items0]);for
(;;)printf{
("选项:\n");for
(int= i 0 ;<i ; size++)iprintf{
("%d.%s\n",+i1,[items]i.)name;}
printf
("0.退出\n");printf
("请输入选项:\n");int
; numscanf
("%d",&)num;if
(0== ) numbreak ;if
(<num 0 || ) num > sizeprintf{
("输入错误,请重新输入\n");continue
;}
[
items-num1].func()list;}
Destory
(&)list;}
list2.c
- #
include#
include#
include#
include"list2.h" GetListSize
Element (*List) listreturn{
; list->size}
void
ShowList (*List) list*{
Node= node ; list->headerwhile
(!=node NULL )printf{
("%d ",)node->e;=
node ; node->next}
printf
("\n");}
void
SearchList (*List) listprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;if
(<index 0 || GetListSize index >= ()list)printf{
("下标输入错误!\n");return
;}
*
Node= p ; list->headerfor
(int= i 0 ;<i ; index++)i={
p ; p->next}
printf
("下标%d的值为%d\n",,index)p->e;}
void
prepend (*List, list)Element e*{
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next ; list->header=
list->header ; node++
list->size;}
void
append (*List, list)Element e//创建节点{
*
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next NULL ;*
Node= p ; list->headerwhile
(NULL!= ) p={
p ; p->next}
=
p->next NULL ;++
list->size;}
bool
insert (*List, listint, index)Element eif{
(<index 0 || GetListSize index > ()list)printf{
("下标输入错误!\n");return
false ;}
//头插
if
(0== || index NULL == ) list->headerprepend{
(,list)e;return
true ;}
//尾插
if
(==index GetListSize ()list)append{
(,list)e;return
true ;}
//创建节点
*
Node= node malloc (sizeof()Node);=
node->e ; e*
Node= p ; list->headerfor
(int= i 0 ;<i - index1;++)i={
p ; p->next}
=
node->next ; p->next=
p->next ; node++
list->size;return
true ;}
void
InsertList (*List) listprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;;
Element eprintf
("请输入插入值:");scanf
("%d",&)e;if
(insert(,list,index)e)printf{
("插入成功!\n");}
elseprintf{
("插入失败!\n");}
}
bool
delete (*List, listint) indexif{
(NULL== ) list->headerreturn false ;if
(<index 0 )return false ;if
(GetListSizeindex >= ()list)return false ;*
Node= p ; list->headerif
(0== ) index={
list->header ; p->nextfree
()p;--
list->size;return
true ;}
for
// 查找插入位置的前一个节点。
index-1
(int= i0;<i-index1;++)i={
p ; p->next}
*
Node= del ; p->next=
p->next ; del->nextfree
()del;--
list->size;return
true ;}
void
DeleteList (*List) listprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;bool
= res delete (,list)index;if
()resprintf ("删除成功\n");else
printf ("删除失败\n");}
void
Destory (*List*) list*{
Node= p ( *)list;->headerwhile
(NULL!= ) p*{
Node= tmp ; p->nextfree
()p;=
p ; tmp}
free
(*)list;*
=list NULL ;}
*
ListCreateList ()*{
List= list malloc (sizeof()List);=
list->header NULL ;=
list->size 0 ;for
(;;);{
Element eint
= num scanf ("%d",&)e;if
(EOF== ) numbreak ;*
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next NULL ;if
(NULL== ) list->header={
list->header ; node}
else*{
Node= n ; list->headerwhile
(!=n->next NULL )={
n ; n->next}
=
n->next ; node}
++
list->size;}
clearerr
(stdin);// 清除EOF状态 return
; list}
void
EditList (*List) listprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;if
(<index 0 || GetListSize index >= ()list)printf{
("下标输入错误!\n");return
;}
*
Node= p ; list->headerfor
(int= i 0 ;<i ; index++)i={
p ; p->next}
printf
("请输入要修改的值:");int
; numscanf
("%d",&)num;=
p->e ; num}
list2.h
- #
pragmaonce #
includetypedef
int ; Elementtypedef
struct Node ;{
Element estruct
Node *; next}
;Nodetypedef
struct List *{
Node; headerint
; size}
;ListGetListSize
Element (*List) list;void
ShowList (*List) list;void
SearchList (*List) list;void
prepend (*List, list)Element e;void
append (*List, list)Element e;bool
insert (*List, listint, index)Element e;void
InsertList (*List) list;bool
delete (*List, listint) index;void
DeleteList (*List) list;void
Destory (*List*) list;*
ListCreateList ();void
EditList (*List) list;List2.c
- 改进1:对
O(n)
进行改进,插入尾节点,使得尾删除的时间复杂度将从O(1)
将为#
include#
include#
include#
include"list2.h" GetListSize
Element (*List) listreturn{
; list->size}
void
ShowList (*List) list*{
Node= node ; list->headerwhile
(!=node NULL )printf{
("%d ",)node->e;=
node ; node->next}
printf
("\n");}
void
SearchList (*List) listprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;if
(<index 0 || GetListSize index >= ()list)printf{
("下标输入错误!\n");return
;}
*
Node= p ; list->headerfor
(int= i 0 ;<i ; index++)i={
p ; p->next}
printf
("下标%d的值为%d\n",,index)p->e;}
void
prepend (*List, list)Element e*{
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next ; list->header=
list->header ; nodeif
(==list->size 0 )={
list->tailer ; node}
++
list->size;}
void
append (*List, list)Element e//创建节点{
*
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next NULL ;if
(NULL== ) list->header={
list->header ; node}
else={
list->tailer->next ; node}
=
list->tailer ; node++
list->size;}
bool
insert (*List, listint, index)Element eif{
(<index 0 || GetListSize index > ()list)printf{
("下标输入错误!\n");return
false ;}
//头插
if
(0== || index NULL == ) list->headerprepend{
(,list)e;return
true ;}
//尾插
if
(==index GetListSize ()list)append{
(,list)e;return
true ;}
//创建节点
*
Node= node malloc (sizeof()Node);=
node->e ; e*
Node= p ; list->headerfor
(int= i 0 ;<i - index1;++)i={
p ; p->next}
=
node->next ; p->next=
p->next ; node++
list->size;return
true ;}
void
InsertList (*List) listprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;;
Element eprintf
("请输入插入值:");scanf
("%d",&)e;if
(insert(,list,index)e)printf{
("插入成功!\n");}
elseprintf{
("插入失败!\n");}
}
bool
delete (*List, listint) indexif{
(NULL== ) list->headerreturn false ;if
(<index 0 )return false ;if
(GetListSizeindex >= ()list)return false ;*
Node= p ; list->headerif
(0== ) index={
list->header ; p->nextfree
()p;if
(NULL== ) list->header={
list->tailer NULL ;}
--
list->size;return
true ;}
for
// 查找插入位置的前一个节点。
index-1
(int= i0;<i-index1;++)i={
p ; p->next}
*
Node= del ; p->next=
p->next ; del->nextfree
()del;--
list->size;if
(==del ) list->tailer={
list->tailer ; p}
return
true ;}
void
DeleteList (*List) listprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;bool
= res delete (,list)index;if
()resprintf ("删除成功\n");else
printf ("删除失败\n");}
void
Destory (*List*) list*{
Node= p ( *)list;->headerwhile
(NULL!= ) p*{
Node= tmp ; p->nextfree
()p;=
p ; tmp}
free
(*)list;*
=list NULL ;}
*
ListCreateList ()*{
List= list malloc (sizeof()List);=
list->header NULL ;=
list->tailer NULL ;=
list->size 0 ;for
(;;);{
Element eint
= num scanf ("%d",&)e;if
(EOF== ) numbreak ;*
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next NULL ;if
(NULL== ) list->header={
list->header ; node}
else*{
Node= n ; list->headerwhile
(!=n->next NULL )={
n ; n->next}
=
n->next ; node}
=
list->tailer ; node++
list->size;}
clearerr
(stdin);// 清除EOF状态 return
; list}
void
EditList (*List) listprintf{
("请输入下标:");int
; indexscanf
("%d",&)index;if
(<index 0 || GetListSize index >= ()list)printf{
("下标输入错误!\n");return
;}
*
Node= p ; list->headerfor
(int= i 0 ;<i ; index++)i={
p ; p->next}
printf
("请输入要修改的值:");int
; numscanf
("%d",&)num;=
p->e ; num}
List2.c
- 改进2:改进1:对
NULL
进行改进,加入一个虚拟头节点并设置为*,尾插和删除的时候不再考虑头节点为NULL的情况
ListCreate ()*{
List= list malloc (sizeof()List);*
Node= node malloc (sizeof()Node);=
list->header ; node=
list->tailer ; node=
list->size 0 ;return
; list}
void
append (*List, list)Element e//创建节点{
*
Node= node malloc (sizeof()Node);=
node->e ; e=
node->next NULL ;=
/*
if(NULL == list->header){
list->header = node;
}else{
list->tailer->next = node;
}
*/
list->tailer->next ; node=
list->tailer ; node++
list->size;}
bool
delete (*List, listint) indexif{
(NULL== ) list->headerreturn false ;if
(<index 0 )return false ;if
(GetListSizeindex >= ()list)return false ;*
Node= p ; list->headerfor
/*
if(0 == index){
list->header = p->next;
free(p);
if(NULL == list->header){
list->tailer = NULL;
}
list->size--;
return true;
}
*/
// 查找插入位置的前一个节点。
index-1
(int= i0;<i-index1;++)i={
p ; p->next}
*
Node= del ; p->next=
p->next ; del->nextfree
()del;--
list->size;if
(==del ) list->tailer={
list->tailer ; p}
return
true ;}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)