赞
踩
上一篇博客讲解了数据结构中的线性结构的一个最简单的结构,顺序结构,本篇文章来讲解稍微复杂点的的结构,单链表。
顺序结构类似于一种结构数组,在一个结构中有一个数组,数组中存放数据,因此一个结构可以存放多个元素。而单链表类似于带有指针的结构体。一个结构只存放一个元素,但是结果与结构之间使用指针相连,构成了一个线性的结构。单链表结构如图所示:
头结点指向表中的第一个结构,一般头结点不存储元素,每个结构中存储一个元素,指针指向下一个后继节点。第一个存储元素的结构成为首结点,最后一个结构成为尾结点,尾结点指针为空。头结点指向首结点,并且单链表一直从头结点开始,一直到最后一个尾结点。
单链表结构定义如下:
- #include <stdio.h>
- #include <malloc.h>
-
- typedef char elemtype; //定义数据类型;
- typedef struct LNode
- {
- elemtype data; //用来存放数据
- struct LNode *next; //指针指向后继节点
- }LinkNode;
在单链表的一些基本操作和顺序表相似,有建立,销毁初始化等操作,但是执行起来却大不相同。在单链表中的操作有:
1.建立单链表
建立单链表的基本操作就是插入结点。将一个新的节点插入到单链表中。例如我们要将结点s插入到节点L后面,基本操作为,先让节点s的后继指针指向L后继指针所指的结点,在将L的后继指针指向s。如图所示:
初始时,结点s不在表中
先将s的后继节点的指针指向L后继节点的指针所指向的结点:如图
在将L后继节点的指针指向s:如图
最后结点成功插入:
代码实现如下:
- s->next=L->next; //将L的后继节点赋给s;
- L->next=s; //将L的后继节点定义为s;
以数组a[n]中的元素为基准建立单链表。其中建立单链表的方式有两种,一种是头插法,另一种是尾插法。头插法是先提取a[i],在建立新节点,从表头开始依次插入结点,而尾插法则是把每个元素都插在表尾。
头插法建立单链表相对简单,直接插在元素头结点后面就可以完成对单链表的建立,代码实现如下:
- void CreateListF(LinkNode *&L,elemtype a[],int n)
- {
- int i=0;
- LinkNode *p; //定义新节点p;
- L=(LinkNode*)malloc(sizeof(LinkNode)); //将要建立的单链表L置为空,在依次插如元素
- L->next=NULL;
- while(i<n)
- {
- p=L=(LinkNode*)malloc(sizeof(LinkNode)); //给p分配存储节点,在将a[i]的值赋给p;
- p->data=a[i];
- p->next=L->next; //将p插入L中
- L->next=p;
- }
- }
如图,将新的节点插在头结点后面,将其他结点“挤”到后面,依次插入,最后建立完成。
尾插法建立单链表相对较复杂,通过一个结点指向单链表的尾结点,将要插入的结点插在该元素后面,插入一个新元素之后,该结点向后移动一位,重新指向新的尾元素。
代码实现如下:
- void CreateListR(LinkNode *&L,int a[],int n)
- {
- LinkNode *p,*q;
- L=(LinkNode*)malloc(sizeof(LinkNode)); //将L置为空,依次插入元素
- L->next=NULL
- p=L; //指针p指向L;
- for(int i=0;i<n;i++)
- {
- q=(LinkNode*)malloc(sizeof(LinkNode));//给q分配存储空间,将数组的值赋给q的元素值
- q->data=a[i];
- q->next=p->next; //将q插入p的后面;
- p->next=q;
- p=q; //p指向尾结点;
- }
- }
如图,指针p始终指向尾结点,插入元素时直接插在p指向的结点后面,依次插入,建立完成。
2.销毁单链表
该操作相对简单,通过定义两个指针p,pre,pre指向单链表的首结点,p指向首结点的后继节点,先释放掉pre,在将pre指向p的后继节点,将p指向pre的后继节点,在删除pre,依次进行删除释放,最后销毁整个单链表。
代码实现如下:
- void DestroyList(LinkNode *&L)
- {
- LinkNode *pre=L,*p=L->next; //pre指向首结点结点,pre指向首结点的后继节点
- while(p!=NULL)
- {
- free(pre); //销毁首结点
- pre=p; //此时新的首结点为p,在将pre指向新的首结点
- p=pre->next; //p指向首结点的后继节点
- }
- free(pre); //删除尾结点,销毁完成
- }
如图所示:
3.初始化单链表
初始化线性表指建立一个空的单链表,相当于建立一个头结点为空的单链表。直接将头结点置为空之后就可以完成改操作。代码实现如下
- void InitList(LinkNode *&L)
- {
- L=(LinkNode*)malloc(sizeof(LinkNode));
- L->next=NULL; //创建头结点并置为空
- }
4.输出单链表
要逐一输出单链表,必须要有一个指针逐一扫描单链表,在将扫描到的元素值依次输出,由于头结点没有不存储元素,因此我们用首结点开始扫描。代码实现如下。
- void DispList(LinkNode *L)
- {
- char e;
- LinkNode *p=L->next; //将指针p指向首结点,相当于头结点的后继节点。
- while(p!=NULL) //如果p不为空,将该节点则输出。
- {
- e=p->data;
- printf("%c",e);
- p=p->next; //输出之后转移到下一个节点
- }
- printd("\n");
- }
5. 求单链表长度
在顺序表中,直接输出顺序表的长度即可。但是在单链表中,没有记录具体的长度,需要通过“数鸭子”一样的方式依次“数”出单链表的长度。同样,先定义一个指针p,让指针p指向首结点,并且记录,在将指针p向后移动,继续记录,直到p为空。代码实现如下:
- int ListLength(LinkNode *&L)
- {
- int i=0; //定义一个基本整形i,将i赋值为0;
- LinkNode *p=L->next; //将指针p指向首结点。
- while(p!=NULL) //若p不为空,表示有节点,i加上一位
- {
- i++;
- p=p->next; //p向后转移一位。
- }
- return (i); //最后返回i;
- }
6.求单链表中的某个元素值
要求单链表中的某个位置的元素值,首先应该找到改位置,然后在“读取”里面的元素值。例如,若要求出单链表中第i个元素的元素值。应该先用一个指针依次扫描并记录,直到扫描到第i个元素。代码实现如下:
- bool GetElem(LinkNode *L,int i,ElemType &e)
- {
- int j=1; //从第一个元素开始记录,将j定义为1
- LinkNode *p=L->next; //p指向首结点
- if(i<=0)
- return false; //如果i为0,则无法查找,返回错误
- while(j<i&&p!=NULL) //向后依次记录元素的个数
- {
- j++;
- p=p->next;
- }
- if(p==NULL) //若p为空,则单链表没有第i个元素,返回错误。
- return false;
- else //找到之后将i赋给e,返回为真,查找完成。
- {
- e=p->data;
- return true;
- }
- }
7.按元素查找
查找单链表中一个与值域相等的元素,同样,需要扫描单链表,如存在,则将该位置返回,不存在则返回0,代码实现如下:
- int LocateElem(LinkNode *L,elemtype e)
- {
- int i=1;
- LinkNode *p=L->next; //p指向首结点
- while(p!=NULL&&p->data!=e) //如果p值域不为e,i加1,p向后移动一位
- {
- i++;
- p=p->next;
- }
- if(p==NULL) //若p为空,则单链表中无该元素,返回0
- return 0;
- else //若p不为空,则将i返回
- return i;
- }
8.将数据元素插入指定的位置
将数据元素elemtype e插入单链表L的第i个位置,首先在单链表中找到第i-1个结点,然后在插入到该结点的后面,代码实现如下:
- bool ListInsert(LinkNode *L,int i,elemtype e)
- {
- int j=1;
- LinkNode *p,*q;
- p=L->next;
- while(j<i&&p!=NULL) //从头结点开始依次查找第i个元素
- {
- j++
- p=p->next
- }
- if(p==NULL) //未找到则返回错误
- return false;
- else //找到之后建立新的节点,再将新的节点插入,操作完成
- {
- q=(LinkNode*)malloc(sizeof(LinkNode));
- q->data=e;
- q->next=p->next;
- p->next=q;
- return true;
- }
- }
9.删除第i个结点,并将该结点用e返回
该运算实现的过程是找到第i-1个结点,直接将第i-1个结点的指针指向第i的结点的后继节点,在释放第i个结点,运算完成,代码实现如下:
- bool ListDelete(LinkNode *&L,int i,elemtype &e)
- {
- int j=1;
- LinkNode *p,q;
- p=L->next;
- while(j<i-2&&p!=NULL) //找到第i-1个元素。
- {
- j++;
- p=p->next;
- }
- if(p==NULL) //若没找到,则返回错我
- return false;
- else
- { //找到之后,如下一个元素为空,也返回错我。
- q=p->next;
- if(q==NULL)
- return false;
- e=q->data; //若不为空,则将第i个元素的值赋给e。
- p->next=q->next; //将第i-1个元素的指针指向第i个元素的后继节点
- free(p); //释放第i个元素,返回真
- return true;
- }
- }
单链表的基本操作已经讲解完成,若有不足和错误之处,欢迎大家在评论区指出,谢谢。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。