单链表的创建,插入,删除以及查找
本文章依据学校的实验作业完成
目录
前言
一、链表是什么?
1.概念
2.链表的分类
二、单链表的创建,插入,删除以及查找
1.单链表的存储结构
2.单链表的创建
3.单链表的插入
4.单链表的删除
5.单链表的查找
6.主函数
7.完整代码
8.编译结果
三、总结
前言
链表是一种物理存储单元上非连续、非顺序的存储结构,由一系列结点组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
一、链表是什么?
1.概念
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的。
逻辑上连续是我们想象的连续,并不是真正的连续。
2.链表的分类
单向双向,带头结点不带头结点,循环非循环,组合起来共有8种
二、单链表的创建,插入,删除以及查找
1.单链表的存储结构
typedef int ElemType; //便于后期的修改 //定义结点类型
typedef struct Node {ElemType data; //单链表中的数据域 struct Node *next; //单链表的指针域
}Node,*LinkedList;
2.单链表的创建
//单链表的建立(头插法)LinkedList ListCreatH() {Node *L;L = (Node *)malloc(sizeof(Node)); //申请头结点空间L->next = NULL; //初始化一个空链表int i=0;ElemType x; //x为链表数据域中的数据while(i<10) {Node *p;p = (Node *)malloc(sizeof(Node)); //申请新的结点 scanf("%d",&x);p->data = x; //结点数据域赋值 p->next = L->next; //将结点插入到表头L-->|2|-->|1|-->NULL L->next = p; i++;}return L; } //单链表的建立(尾插法)(注:比较常用)LinkedList ListCreatT() {Node *L;L = (Node *)malloc(sizeof(Node)); //申请头结点空间L->next = NULL; //初始化一个空链表Node *r;r = L; //r始终指向终端结点,开始时指向头结点 int i=0 ; //x为链表数据域中的数据for(i=0;i<10;i++){ Node *p;p = (Node *)malloc(sizeof(Node)); //申请新的结点 scanf("%d",&p->data);r->next = p; //将结点插入到表头L-->|1|-->|2|-->NULL r = p; //将r结点移动到最后一个节点}r->next = NULL; //让r结点的指针域置空(链表创建完成)return L; }
3.单链表的插入
//单链表的插入,在链表的第i个位置插入x的元素
/*初始条件:单链表L已存在,1<=i<=ListLength(L)*/
/*在L中第i个位置之前插入新的数据元素e,L的长度加1*/
LinkedList ListInsert(LinkedList L,int i,ElemType x) {LinkedList pre; //pre为前驱结点 pre = L;int tempi = 0;for (tempi = 1; tempi < i; tempi++) {pre = pre->next; //查找第i个位置的前驱结点 }Node *p; //插入的结点为pp = (Node *)malloc(sizeof(Node));p->data = x; //主要代码p->next = pre->next; //主要代码pre->next = p;return L;
}
4.单链表的删除
//单链表的删除,在链表中删除第i个数据元素
/*初始条件:单链表L已存在,1<=i<=ListLength(L)*/
/*操作结果:删除L的第i个数据元素,L的长度减1*/
LinkedList ListDelete(LinkedList L,int i)
{LinkedList p,q; int j=2; p = L->next;while(p->next&&jnext;++j;}if(!(p->next)||j>i) //第i个元素不存在printf("第i个元素不存在\n");q=p->next; p->next=q->next; //将q的后继赋值给p的后继 free(q); //释放q结点return L;
}
5.单链表的查找
//单链表的查找
/*初始条件:单链表L已存在,1<=i<=ListLength(L)*/
/*操作结果:用e打印中第i个数据元素的值*/ void GetElem(LinkedList L){int i,j=1; //j为计数器 int *e;LinkedList p; //声明一结点p printf("请输入查找的位置:");scanf("%d",&i);p=L->next; //让p指向链表L的第一个结点 while(p&&jnext; //让p指向下一个结点 ++j; }if(!p||j>i) //链表p为空否则链表长度过短printf("第i个元素不存在"); //第i个元素不存在 *e=p->data; //取第i个元素的数据 printf("%d\n",*e);}
6.主函数
int main() {LinkedList list,start;printf("请输入单链表的数据:\n"); list = ListCreatT();printf("成功创建链表:\n");for(start = list->next; start != NULL; start = start->next) {printf("%d ",start->data);}printf("\n");menu();int i,option;ElemType x;do{printf("请输入选项:");scanf("%d",&option);switch(option){case 1:{printf("请输入插入数据的位置:");scanf("%d",&i);printf("请输入插入数据的值:");scanf("%d",&x);ListInsert(list,i,x);printf("插入后的链表为:");//打印链表 for(start = list->next; start != NULL; start = start->next){printf("%d ",start->data);}printf("\n");break;}case 2:{int i; printf("请输入删除的位置\n");scanf("%d",&i);ListDelete(list,i);printf("删除后的链表为:");//打印链表for(start = list->next; start != NULL; start = start->next){printf("%d ",start->data); }printf("\n");break; }case 3:GetElem(list); break; case 0:break; default:printf("输出错误!\n");break;} }while(option>0);return 0;
}
7.完整代码
#include
#include typedef int ElemType; //便于后期的修改 //定义结点类型
typedef struct Node {ElemType data; //单链表中的数据域 struct Node *next; //单链表的指针域
}Node,*LinkedList;//建立菜单 void menu(){printf("*****1.单链表的插入*****\n");printf("*****2.单链表的删除*****\n");printf("*****3.单链表的查找*****\n");printf("*****0. 退出 *****\n");}//单链表的初始化LinkedList LinkListInit() {Node *L;L = (Node *)malloc(sizeof(Node)); //申请结点空间 if(L == NULL) //判断是否有足够的内存空间{ printf("申请内存空间失败\n");}L->next = NULL; //将next设置为NULL,初始长度为0的单链表 return L;
}//单链表的建立(头插法)LinkedList ListCreatH() {Node *L;L = (Node *)malloc(sizeof(Node)); //申请头结点空间L->next = NULL; //初始化一个空链表int i=0;ElemType x; //x为链表数据域中的数据while(i<10) {Node *p;p = (Node *)malloc(sizeof(Node)); //申请新的结点 scanf("%d",&x);p->data = x; //结点数据域赋值 p->next = L->next; //将结点插入到表头L-->|2|-->|1|-->NULL L->next = p; i++;}return L; } //单链表的建立(尾插法)LinkedList ListCreatT() {Node *L;L = (Node *)malloc(sizeof(Node)); //申请头结点空间L->next = NULL; //初始化一个空链表Node *r;r = L; //r始终指向终端结点,开始时指向头结点 int i=0 ; //x为链表数据域中的数据for(i=0;i<10;i++){ Node *p;p = (Node *)malloc(sizeof(Node)); //申请新的结点 scanf("%d",&p->data);r->next = p; //将结点插入到表头L-->|1|-->|2|-->NULL r = p; //将r结点移动到最后一个节点}r->next = NULL; //让r结点的指针域置空 return L; }//单链表的插入,在链表的第i个位置插入x的元素
/*初始条件:单链表L已存在,1<=i<=ListLength(L)*/
/*在L中第i个位置之前插入新的数据元素e,L的长度加1*/
LinkedList ListInsert(LinkedList L,int i,ElemType x) {LinkedList pre; //pre为前驱结点 pre = L;int tempi = 0;for (tempi = 1; tempi < i; tempi++) {pre = pre->next; //查找第i个位置的前驱结点 }Node *p; //插入的结点为pp = (Node *)malloc(sizeof(Node));p->data = x; p->next = pre->next;pre->next = p;return L;
} //单链表的删除,在链表中删除第i个数据元素
/*初始条件:单链表L已存在,1<=i<=ListLength(L)*/
/*操作结果:删除L的第i个数据元素,L的长度减1*/
LinkedList ListDelete(LinkedList L,int i)
{LinkedList p,q; int j=2; p = L->next;while(p->next&&jnext;++j;}if(!(p->next)||j>i) //第i个元素不存在printf("第i个元素不存在\n");q=p->next; p->next=q->next; //将q的后继赋值给p的后继 free(q);return L;
} //单链表的查找
/*初始条件:单链表L已存在,1<=i<=ListLength(L)*/
/*操作结果:用e打印中第i个数据元素的值*/ void GetElem(LinkedList L){int i,j=1; //j为计数器 int *e;LinkedList p; //声明一结点p printf("请输入查找的位置:");scanf("%d",&i);p=L->next; //让p指向链表L的第一个结点 while(p&&jnext; //让p指向下一个结点 ++j; }if(!p||j>i)printf("第i个元素不存在"); //第i个元素不存在 *e=p->data; //取第i个元素的数据 printf("%d\n",*e);}int main() {LinkedList list,start;printf("请输入单链表的数据:\n"); list = ListCreatT();printf("成功创建链表:\n");for(start = list->next; start != NULL; start = start->next) {printf("%d ",start->data);}printf("\n");menu();int i,option;ElemType x;do{printf("请输入选项:");scanf("%d",&option);switch(option){case 1:{printf("请输入插入数据的位置:");scanf("%d",&i);printf("请输入插入数据的值:");scanf("%d",&x);ListInsert(list,i,x);printf("插入后的链表为:");//打印链表 for(start = list->next; start != NULL; start = start->next){printf("%d ",start->data);}printf("\n");break;}case 2:{int i; printf("请输入删除的位置\n");scanf("%d",&i);ListDelete(list,i);printf("删除后的链表为:");//打印链表for(start = list->next; start != NULL; start = start->next){printf("%d ",start->data); }printf("\n");break; }case 3:GetElem(list); break; case 0:break; default:printf("输出错误!\n");break;} }while(option>0);return 0;
}
8.编译结果

三、总结
常考的知识点:链表的插入,删除的关键语句、在头部插入,中间插入,尾部插入的时间复杂度,以及单链表和顺序表的区别
在链表尾部添加(addLast())需要从头遍历,时间复杂度为O(n)
在链表头部添加(addFirst()),时间复杂度为O(1)
在链表任意位置添加(add(int index,E e)),平均情况下为O(n/2)=O(n)
单链表和顺序表的区别:
顺序表的优点:
- 元素可以随机存储
- 节省存储空间
- 元素位置可用一个简单、直观的公式表示并在常量时间内访问
顺序表的缺点:
- 在作插入或删除操作时,需要移动大量元素
单链表的优点:
- 链表是线性表的链式存储表示
- 链表中逻辑关系相邻的元素不一定在存储位置上相连,用一个链(指针)表示元素之间的邻接关系即:链表中结点的逻辑顺序和物理顺序不一定相同
- 在插入和删除时,不需要大量移动数据元素,只需找到结点,对该结点做删除和插入的工作即可
单链表的缺点:
在访问第i个位置的元素时,需要遍历链表,不能想顺序表一样直接找到第i个位置。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
