赞
踩
1,为什么引入链表?
由于顺序表的插入,删除需要移动大量的元素,影响了运行效率。因此引入了线性表链式存储。逻辑上相邻的元素不要求物理地址也相邻,通过链来建立数据元素之间的关系
2,链表的定义
- typedef int Elemtype;
- typedef struct LNode{
- Elemtype data;//存储本节点的数据
- struct LNode *next;//存储下一个节点的地址
- }LNode,*LinkList;//结构体的变量
3,链表头插入法解读
-
- LinkList CreatList_H(LinkList &L){
- LNode *s;
- int x;
- L = (LinkList)malloc(sizeof(LNode));//创建初始头节点
- L->next=NULL;//L->的形式调用结构体成员,因为L是指针类型,当然也可以(*L).next进行调用,这是把*L看成变量
- scanf("%d",&x);
- while(x!=9999){//输入9999表示停止输入
- s=(LNode*)malloc(sizeof(LNode));//创建新节点
- s->data=x;//为节点赋值
- s->next=L->next;//将节点插入链表,L为头指针
- L->next=s;
- scanf("%d",&x);
- }
- return L;
- }
4,链表尾插入法解读
- LinkList CreatList_R(LinkList &L){
- int x;
- L = (LinkList)malloc(sizeof(LNode));//创建初始头节点
- LNode *s,*r=L;//r是表尾指针
- scanf("%d",&x);
- while(x!=9999){//输入9999表示停止输入
- s=(LNode*)malloc(sizeof(LNode));
- s->data=x;
- r->next=s;//将s插到链表尾指针r的后面
- r=s;//r是一个暂时存放尾指针的变量,将新链表的尾指针地址s存到r上
- scanf("%d",&x);
- }
- r->next=NULL;
- return L;
- }
5,按顺序查找第i个节点
- LNode *GetElem(LinkList &L,int i){
- int j=1;//用来计数
- LNode *p=L->next;
- if(i==0)//返回头节点
- return L;
- if(i<1)//i无效,返回NULL
- return NULL;
- while(p&&j<i){//当前节点的指针域不为空,说明有下个节点。并且j<i时执行
- p=p->next;//当j=i-1时,p存储的是i节点的地址
- j++;
- }
- return p;
- }
6,按值查找节点
- LNode *GetElem2(LinlList &L,Elemtype value){
- LNode *p=L->next;//p为头结点
- while(p){//下一个节点存在
- if(p->data==value )
- return p
- else
- p=p->next;//遍历下一节点
- }
- return NULL;
- }
7,在链表pos插入节点value
- bool Insert_Front(LinkList &L,int pos,Elemtype value){
- LNode *p=GetElem(L,pos-1);//获取到pos的前一个节点
- if(p==NULL){//如果插入位置的前一节点不存在。
- printf("插入位置不合法");
- return false;
- }
- LNode *newNode=(LNode*)malloc(sizeof(LNode));//为新节点分配存储空间
- newNode->data=value;//为新节点赋值
- newNode->next=p->next;//插入到链表中
- p->next=newNode;
- return true;
- }
8,删除pos位置的值
- bool Delete_Node(LinkList &L,int pos){
- LNode *p=GetElem(L,pos-1);//获取到pos的前一个节点
- LNode *q=p->next;//待删除的节点
- if(p==NULL){//如果插入位置的前一节点不存在。
- printf("待删除的节点位置不存在");
- return false;
- }
- p->next=q->next;
- free(q);
- printf("删除成功\n");
- return true;
- }
9,求表长
- int length(LinkList &L){
- LNode *p=L->next;
- int length=0;
- while(p){
- length++;
- p=p->next;
- }
- printf("表长为%d\n",length);
- return length;
-
- }
二,双链表
1,为什么要引入双链表?
因为单链表中,只有后继节点的指针,这使单链表只能只能从头节点依次遍历链表。当我们需要访问某个节点的前驱节点时,就只能从头遍历,很不方便。这样访问后继节点的时间复杂度为O(1),访问前驱节点的时间复杂度为O(n)。为了克服这个缺点我们在结构体中再加入前驱节点的指针域,这就是双链表
优势:
2,双链表定义
- typedef struct Dnode{
- Elemtype data;
- struct Dnode *prior,*next;
- }DNode,*DLinkList;
3,在p后插入s操作的核心
- s->next=p->next;
- p->next-prior=s;
- p->next=s;
- s->prior=p;
4,删除p后面的q操作的核心
- p->next=q->next;
- q->next->prior=p;
- free(q);
1,存取方式:
顺序表可以顺序存取,也可以随机存取。链表只能从表头顺序存取元素
2,逻辑结构与物理结构:
采用顺序存储,逻辑上相邻的元素,物理存储位置也相邻。链表存储,逻辑上相邻的元素,物理存储位置不一定相邻。
3,查找,插入和删除操作
4,空间分配:
1,基于存储考虑:
当线性表长度或者存储规模难以估计时,采用链表
2,基于运算考虑:
按序查找,顺序表时间复杂度为O(1),链表为O(n),如果经常使用按序查找考虑使用顺序存储
当数据元素的信息量很大时,又会频繁地对表进行插入,删除操作,因为顺序存储平均需要移动半个表的元素,因此考虑使用链表
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。