20150405_链表
来源:互联网 发布:linux jenkins svn 编辑:程序博客网 时间:2024/05/29 13:11
20150405_链表
链表(Linked list):是一种常见的数据结构,是一种线性表,但并不会按线性的存储数据,而是每个结点里存着指向下一个结点的指针。
- 优点:由于不必按顺序存储,链表在插入式的时间复杂度为O(1)。
- 缺点:查找或访问特定结点需要遍历,不支持随机查找和访问,时间复杂度O(n)。
单链表
1.结构定义
typedef struct LNode{ ElemType data; // 在此定义链表的成员 struct Node *next;}LNode, * Linklist; //LNode 为链表结点的类型,Linklist为链表的类型
2.创建链表
//带头结点void ini_linklist(Linklist *L){ (*L)=(Linklist)malloc(sizeof(LNode));//这一句不可以少 (*L)->next=NULL;}//在这里,创建链表,要对实参进行改变,所以对于类型linklist要传地址过来。笔者刚学习的时候对这些不太了解,所以又有如此下的一种写法,可以暂时规避这个问题。Linklist ini_linklist(void){ Linklist L; L=(Linklist)malloc(sizeof(LNode)); L->next=NULL; return L;}//不带头结点Linklist ini_linklist(void){ Linklist head; head=NULL; //注意这句别写错了,不然下面的都会出现问题 return head;}
3.头插法
顾名思义,将结点查到链表的最前头,使其成为第一个结点(若是带头结点的链表,则插入在头结点后)
说明:无论插入还是删除,我们都需要知晓我们操作结点的前驱结点的位置。
关键代码
//**带头结点的头插法**//说明:pnew为插入结点,pre为pnew的前驱,这里应为头结点Lpnew->next=L->next;L->next=pnew;//**不带头结点的头插法**//说明:笔者习惯用L表示不存储数据的头结点,对于存储数据的头结点使用head表示pnew->next=phead;
下面附上两个实现的头插法版本
//首先是带头结点的void head_insert(Linklist *L){ Linklist pnew; int val; while(scanf("%d",&val)!=EOF) { pnew=(Linklist)malloc(sizeof(LNode)); pnew->next=NULL; //其实这里这句可以不写,但是建议养成习惯,创建完备的结点,防止出现野指针。 pnew->data=val; pnew->next=(*L)->next; (*L)->next=pnew; }}
//不带头结点版本void show_link(Linklist head){ Linklist ptr; ptr=head; if(head==NULL) { printf("the linklist is empty\n"); return ; } while(ptr!=NULL) { printf("%d ",ptr->data); ptr=ptr->next; } printf("\n");}
4.尾插法
尾插法,插入在链表现有元素的最后一个元素(tail)之后。
关键代码
//在这里有没有头结点操作没有不同,除非使用尾插法初始化的是第一个元素,这里我们不讨论这个问题,会在下面的具体实例里处理//说明:pnew为待插入结点,ptail为尾元素,也将成为pnew的前驱。pnew->next=ptail->next;ptail->next=pnew;ptail=pnew;
下面附上两个版本的尾插法
//带头节点版本#include "myfunc.h"void tail_insert(Linklist *L){ Linklist pnew; Linklist ptail; int val; ptail=(*L); while(ptail->next!=NULL) { ptail=ptail->next; } //尾插 while(scanf("%d",&val)!=EOF) { pnew=(Linklist)malloc(sizeof(LNode)); pnew->next=NULL; pnew->data=val; pnew->next=ptail->next; ptail->next=pnew; ptail=pnew; }}
//不带头结点版本void tail_insert(Linklist *head){ Linklist pnew; Linklist ptail; int val,ret; ptail=(*head); if(ptail==NULL) { ret=scanf("%d",&val); if(ret!=1) return ; ptail=(Linklist)malloc(sizeof(LNode));//head为空,必须为ptail分配一个地址空间,让head指向它 ptail->data=val; ptail->next=NULL; (*head)=ptail; } while(ptail->next!=NULL) { ptail=ptail->next; //对于非空链表,遍历到正确的ptail位置 } //尾插 while(scanf("%d",&val)!=EOF) { pnew=(Linklist)malloc(sizeof(LNode)); pnew->next=NULL; pnew->data=val; pnew->next=ptail->next; ptail->next=pnew; ptail=pnew; }}
5.删除
关键代码
//说明:ptr为操作结点指针,pre为其前驱pre->next=ptr->next;free(ptr);//只能释放由malloc,realloc等分配的空间,你如果不知道是否是这样的分配,最好不写。
还是惯例,附上两个删除版本
//带头结点void delete_link(Linklist *L,int val){ Linklist pre; Linklist ptr; pre=(*L); ptr=(*L)->next; if(ptr==NULL) { printf("it's an empty linklist\n"); return ; } while(ptr!=NULL) { if(ptr->data==val) { pre->next=ptr->next; free(ptr); printf("success\n"); return ; } pre=ptr; ptr=ptr->next; } printf("no such datum\n");}
//不带头结点版本#include "myfunc.h"void delete_link(Linklist *head,int val){ Linklist ptr,pre; ptr=(*head); if(ptr==NULL) { printf("the linklist is empty\n"); return ; } if(ptr->data==val) { ptr=ptr->next; (*head)=ptr; return ; } pre=ptr; ptr=ptr->next; while(ptr!=NULL) { if(ptr->data==val) { pre->next=ptr->next; free(ptr); printf("success\n"); return ; } pre=ptr; ptr=ptr->next; } printf("no such value\n");}
0 0
- 20150405_链表
- 数据结构_链表_单向链表
- C++_链表
- C语言_链表
- java_数据结构_链表
- 链表_删除函数
- 04_链表
- 数据结构_链表
- leetcode总结_链表
- 线性结构_链表
- 离散存储_链表
- 链表_小记
- ^_^
- ^_^
- ^_^
- ^_^
- *_&
- ...!@~....!@#....+_#%.
- hdoj 1078 fatmouse and cheese 记忆化搜索
- iOS项目完成后上传到apple Store的流程以及注意事项
- Light OJ 1141--BFS--(隐蔽的BFS)
- 第十一讲_项目一_分离三位数
- 【leetcode】Minimum Path Sum
- 20150405_链表
- C++ vector 使用
- android studio最基本的知识一
- LeetCode66/169/79 Plus One/Majority Element /Word Search
- linux ls和 ll 命令
- HTML5-canvas 绘图
- 依赖关系
- 破解TexturePacker加密资源
- 【leetcode】Unique Paths