- 什么是单链表?
由于顺序表在插入和删除是需要做大量的元素移动工作,而且需要连续的物理空间,因此其缺点是十分明显的,为了解决这一问题,不需要预先分配连续的内存地址空间、插入删除元素不需要做大量移动工作的链表出现了。但解决问题的同时也拥有自己的缺点,即不能随机存取。
在链表中,每个数据元素是一个节点,每个节点包含两部分,存续元素信息的数据域和存储后继节点存储位置的指针域。
其中,头指针指示链表中第一个节点的存储位置,头结点为在第一个元素前附设的一个节点,最后一个节点因为没有后继节点,因此指针域为空。
正是因为链表的这种结构,导致链表不可以随机访问数据元素,只能从第一个元素一个一个的访问,因此,对于单链表来说,插入删除元素是高效的,而访问元素是低效的。
以下为单链表的C语言实现。
- 需要提前定义好的内容
1 #include<stdio.h> 2 #include<malloc.h> 3 #define SIZE 100 4 #define INCREMENT_SIZE 10 5 #define TRUE 1 6 #define FALSE 0 7 #define OK 1 8 #define ERROR 0 9 #define OVERFLOW -2 10 typedef int Status;//Status 代替了 int 11 typedef int ElemType;
注意,malloc
.h,是动态存储分配函数头文件,
当对内存区进行操作时,要调用相关函数。
- 结点
1 typedef struct LNode 2 { 3 int data; 4 LNode *next; 5 }LNode,*LinkList;
使用结构体定义节点,包含数据域和指针域。
- 头插法建立单链表
1 void CreateList_L(LinkList &L,int n){ 2 //逆序输入n个元素的值,建立带表头节点的单链表L 3 L=(LinkList)malloc(sizeof(LNode)); 4 L->next=NULL;// 先建立一个带头结点的单链表 5 int i; 6 LinkList p; 7 for(i=n;i>0;--i){ 8 p=(LinkList)malloc(sizeof(LNode));//生成新节点 9 printf("请输入元素值:"); 10 scanf("%d",&p->data);//输入元素值 11 p->next=L->next;L->next=p; //插入到表头 12 } 13 } //CreatList_L
头插法,每次插入元素时都在头结点后面插入新的数据元素,因此,插入完成后的单链表的顺序与插入的顺序相反。与此相应还有尾插法。
- 在指定位置插入数据元素
1 Status ListInsert_L(LinkList &L,int i,ElemType e){ 2 //在带头结点的单链线性表L中第i个位置之前插入元素e 3 LinkList p=L;int j=0; 4 while(p&&j<i-1){ 5 p=p->next;++j; 6 }//寻找第i-1个节点 7 if(!p||j>i-1) return ERROR; 8 LinkList s; 9 s=(LinkList)malloc(sizeof(LNode)); 10 s->data=e;s->next=p->next; 11 p->next=s; 12 return OK; 13 }//ListInsert_L
- 删除第i个元素
1 Status ListDelete_L (LinkList &L,int i,ElemType &e){ 2 //在带头结点的单链表L中,删除第i个元素,并由e返回其值 3 LinkList p; 4 LinkList q; 5 p=L; int j=0; 6 while(p->next&&j<i-1){//寻找第i个节点,并令p指向其前驱 7 p=p->next;++j; 8 } 9 if(!(p->next)||j>i-1) return ERROR; //删除位置不合理 10 q=p->next;p->next=q->next;//删除并释放节点 11 e=q->data; free(q); 12 return OK; 13 14 }//ListDelete_L
- 获取第i个元素的值
1 Status GetElem_L(LinkList L,int i,ElemType &e){ 2 //L为带都节点的单链表的指针 3 //当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR 4 LinkList p; 5 p=L->next;int j=1; 6 while(p&&j<i){ 7 p=p->next;++j; 8 } 9 if(!p||j>i) return ERROR; 10 e=p->data; 11 return OK; 12 }//GetElem_L
- 输出单链表的所有元素
void printL(LinkList L){ LinkList p; p=L->next; while(p!=NULL){ printf("%d ",p->data); p=p->next; } }
- main函数
1 int main(){ 2 LinkList L; 3 CreateList_L(L,4);//创建一个单链表,并指定单链表的长度。 4 printL(L); 5 printf("\n"); 6 int insert; 7 printf("请输入要插入的元素:"); 8 scanf("%d",&insert); 9 ListInsert_L(L,1,insert); 10 printf("插入后的链表元素为:"); 11 printL(L); 12 printf("\n"); 13 int a; 14 int i; 15 printf("请输入要删除第几个元素:"); 16 scanf("%d",&i); 17 ListDelete_L (L,i,a); 18 printL(L); 19 20 }
以上是单链表的介绍。除此之外,还有很多其他形式的链表。
- 循环链表
- 双向链表
- 静态链表