线性表的链式存储
2015-03-13 15:18
330 查看
线性表的链式存储。主要是单链表的相关知识,介绍了正序建立单链表、逆序建立单链表、单链表的插入、删除、查找、输出以及单链表的合并方法。单链表的合并前提是两个都有序。具体知识点详见代码注释。
/*** 线性表的链式存储结构不能随机存储,整个链表的存取都必须从头结点开始。但是没有顺序存储的缺点:插入或者删除时需要移动大量元素 其特点是用一组任意的存储空间存储线性表的数据元素 结点:数据域和指针域 */ #include<stdio.h> #include<stdlib.h> #define MAX 100000 //**********************线性表的单链表存储结构*********************** typedef struct LNode { int data; //数据域 struct LNode *next; //指针域 } LNode,*LinkList; //LinkList是LNode型结构的指针 //**************************头插法逆序建立单链表**************************** void CreateList_L1(LinkList &L,int n) { //逆位序输入n个元素值,建立带有头结点的单链表,时间复杂度为O(n) L->next = NULL;//先建立个带有头结点的单链表L,使头结点指针域为空, for (int i = n; i > 0; --i) { LinkList p = (LinkList)malloc(sizeof(LNode));//生成新结点 scanf("%d",&p->data); //插入到表头 p->next = L->next; L->next = p; } } //**************************尾插法正序建立单链表**************************** void CreateList_L2(LinkList &L,int n) { //借助一个中间变量,正序建立n个元素的单链表,时间复杂度仍然为O(n) //先建立个带有头结点的单链表L,头结点指针域为空,默认使用Linklist建立L是即为空 LinkList r = L; for (int i = 0; i < n; ++i) { LinkList p = (LinkList)malloc(sizeof(LNode));//生成新结点 scanf("%d",&p->data); //插入到表尾 r->next = p; r = p; } r->next = NULL; } //**************************按序输出单链表的各个元素**************************** void PrintList_L(LinkList L) { LinkList p = L->next;//p指向第一个元素 while(p) { printf("%d ", p->data); p = p->next; } } //***********************取出指定位序的单链表中的数据元素*********************** int GetElem_L(LinkList L,int i) { //时间复杂度为O(n) //L为带头结点的单链表的头指针 //返回链表的第i个元素,若没有,则错误提示 LNode *p = L->next; //初始化,p指向第一个结点 int j = 1;//计数器 int e;//返回值 while(p && j<i) { //顺指针向后查找,知道p指向第i个元素或者p为空 p = p->next; ++j; } if (!p || j>i) { printf("没有找到该元素,请确认后重新输入位序!\n"); e = MAX; return e; } e = p->data; return e; } //*******************向单链表的指定位序插入一个元素******************** void ListInsert_L(LinkList &L,int i,int e) { //在带头结点的单链表L的第i个位置之前插入元素e,1=<i<=length(L)+1,时间复杂度为O(n) /* LNode *p = L->next; //初始化,p指向第一个结点,下面一句话效果一样,因为LinkList是指向LNode型的指针变量,无需再加*号 LinkList p = L->next; int j = 1;//计数器 */ //上面使p指向第一个结点的方法有问题,如果要将元素插在第一位会有bug,故要从头结点开始 LinkList p = L; int j = 0; while(p && j<i-1) { p = p->next; //寻找第i-1个结点,使p指向它 ++j; } if (!p || j>i-1) { printf("要插入的位置没有找到,可能是插入位序有误!\n"); getchar(); exit(1); } LinkList s = (LinkList)malloc(sizeof(LNode));//生成一个结点s s->data = e; //插入结点 s->next = p->next; p->next = s; } //********************删除单链表的指定位序的一个元素******************** void ListDelete_L(LinkList &L,int i) { //时间复杂度为O(n) //在带头结点的单链表L中,删除第i个位置的元素.i<=length(L) LNode *p = L; //初始化,p指向头结点 int j = 0;//计数器 while(p->next && j<i-1) { p = p->next; //使p指向被删除结点的前一个结点,即p指向i-1 ++j; } if (!(p->next) || j>i-1) { //要保证p的后一个元素有值,即被删除元素存在 printf("删除位置不合理,请重新确认!\n"); getchar(); exit(1); } //删除该元素 LNode *q = p->next; p->next = q->next; free(q);//释放结点 } //**************************有序链表的合并****************************** void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc) { //已知单链线性表La和Lb的元素按值非递减排序 //归并La和Lb得到新的单链表Lc,Lc的元素也按值非递减排列 LinkList pa,pb,pc; pa = La->next; pb = Lb->next; //用La的头结点作为Lc的头结点 pc = La; Lc = pc; while(pa && pb) { if (pa->data <= pb->data) { pc->next = pa; pc = pa; pa = pa->next; } else { pc->next = pb; pc = pb; pb = pb->next; } } pc->next = pa?pa:pb; free(Lb);//释放Lb的头结点 } int main() { //定义3个链表,初始化3个头结点 LinkList la = (LinkList)malloc(sizeof(LNode)); LinkList lb = (LinkList)malloc(sizeof(LNode)); LinkList lc;// int count;//计数使用,链表初始化时记录链表元素个数 int location,value;//插入时的位置和值 char c; //使用头插法逆序建立链表 printf("请输入la链表元素个数:"); scanf("%d",&count); CreateList_L1(la,count); printf("逆序建立的la链表元素为:"); PrintList_L(la); //使用尾插法正序建立链表 printf("\n\n请输入链表lb元素个数:"); scanf("%d",&count); CreateList_L2(lb,count); printf("正序建立的lb链表元素为:"); PrintList_L(lb); //向正序建立的单链表中插入数据 printf("\n\n请输入lb插入位置和插入值:"); scanf("%d%d",&location,&value); ListInsert_L(lb,location,value); printf("插入元素之后的链表元素为:"); PrintList_L(lb); //继续测试该链表的删除效果 printf("\n\n请输入lb删除位置:"); scanf("%d",&location); ListDelete_L(lb,location); printf("删除元素之后的链表元素为:"); PrintList_L(lb); //测试GetElem函数是否有效 printf("\n\n请输入需要得到的元素位置:"); scanf("%d",&location); value = GetElem_L(lb,location); if (value == MAX) { printf("输入错误或者没有该位置的元素!\n"); }else { printf("该元素的值为:%d",value); } //测试两个链表的归并,前提是两个链表都有序 MergeList_L(la,lb,lc); printf("\n\n两个链表合并后lc的元素是:"); PrintList_L(lc); return 0; }
相关文章推荐
- 线性表的链式存储
- 【Data_Structure笔记2】线性表的链式存储【单链表】
- 线性表的顺序存储和链式存储
- 线性表的链式存储
- 线性表之链式存储结构_单链表相关算法
- 线性表的链式存储(LinkList)
- 关于线性表的链式存储(链表)的创建,头插法,尾插法,删除链表结点的操作
- 艾伟_转载:C#版数据结构之--线性表的链式存储(单链表)
- 结构之美:线性表的链式存储结构——链表
- 2007.08.19线性表的链式存储
- 线性表的链式存储
- 线性表链式存储结构的C++模板类程序源代码
- 线性表的链式存储结构之单链表类的实现_Java
- 线性表的链式存储C语言版
- 线性表链式存储的实现
- 数据结构一一线性表的链式存储结构之插入与遍历
- 线性表的链式存储
- 线性表链式存储_api函数实现
- JAVA数据结构 线性表的链式存储及其实现
- 线性表的链式存储