线性表的链式存储结构(LinkList)
前言
为了克服顺序表的缺点,可以采用链式方式存储线性表。通常将采用链式存储结构的线性表称为线性链表。
在顺序表中,用一组地址连续的存储单元来依次存放线性表的节点,因此节点的逻辑顺序和物理顺序是一致的。而链表则不然,链表是用一组任意的存储单元来存放线性表的节点,这组存储单元可以是连续的,也可以是非连续的,甚至是零散分布和内存的任何位置上。
示意图
为了正确地表示结点间的逻辑关系,必须在存储线性表的每个数据元素值的同时,存储指示其后续的地址信息,这两部分信息组成的存储映像称为结点(Node)
结点表示图
LinkListNode.PNG结点包括两个域:数据域用来存储结点的值,指针域用来存储数据元素的直接后续的地址。
单链表中每个节点的存储地址存放在其前驱结点的指针域中,由于线性表中的第一个结点无前驱,所以应设一个头结点H指向第一个结点。由于线性表的最后一个结点没有直接后继,则指定单链表的最后一个结点的指针域为“空”(NULL)。这里称为H。在H结点的数据域中,我们可以存放整个表的长度值。那么一个单链表的存储示意图为
单链表表示图
我们理解的逻辑图:
LinkListExample.PNG
实际中可能的存储地址图:
LinkListAdd.PNG
线性表链式存储的表示
可以理解为将不同的地址连起来存储我们需要的值,用来节约内存空间,消除碎片。
1、定义一个节点(使用结构体)
LinkList.h
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
typedef struct Node
{
int data;
Node *next;
}Node,*LinkList;
LinkList init(LinkList L); //初始化表
int length(LinkList L); //得到总长度
int get_int(LinkList L,int loc); //根据下标得到存储的值
void get_all(LinkList L); //得到所有存储的值
void add(LinkList L,LinkList element); //新增
bool del(LinkList L,int loc); //根据下标删除
bool update(LinkList L,int loc,int new_element); //更新
bool empty(LinkList L); //判断是否为空
bool clear(LinkList L); //清空表
LinkList destory(LinkList L); //销毁表
void insert(LinkList L,int loc,int element); //插入数据
#endif
这里面我们首先定义了一个结构体作为节点,表示每个位置前面图中的结点,这里有两个内容,data是用来存放数据的(头结点中存放表长度),next表示下一个结点的地址(没有就为NULL),下面那些是我们需要完成的方法。
2、完成相应的方法
LinkList.cpp
#include <stdio.h>
#include "LinkList.h"
#include <malloc.h>
LinkList init(LinkList L) //初始化表
{
L = (LinkList)malloc(sizeof(Node)); //头指针
L->next = NULL;
L->data = 0;
printf("init success!!\n");
return L;
}
int length(LinkList L) //得到总长度
{
return L->data;
}
int get_int(LinkList L,int loc) //根据下标得到存储的值
{
if(loc < 0 || loc > L->data-1)
{
printf("the loc don't exists!!\n");
return -1;
}
LinkList p = L;
int i=0;
while(p->next != NULL && i<=loc)
{
p = p->next;
i++;
}
return p->data;
}
void get_all(LinkList L) //得到所有存储的值
{
if(L->data == 0)
{
printf("the list is null\n");
return;
}
LinkList p = L;
while(p->next != NULL )
{
p = p->next;
printf("%7d",p->data);
}
}
void add(LinkList L,int data) //新增
{
LinkList element = (LinkList)malloc(sizeof(Node));
element->data = data;
element->next = NULL;
LinkList p = L;
while(p->next != NULL){
p = p->next;
}
p->next = element;
L->data++;
}
bool del(LinkList L,int loc) //根据下标删除
{
LinkList p = L,q;
int i=0;
while(p->next != NULL && loc > i)
{
p = p->next;
i++;
}
q = p->next;
p->next = q->next;
q->next = NULL;
q->data = NULL;
q = NULL;
L->data--;
printf("del success!\n");
return true;
}
bool update(LinkList L,int loc,int new_element) //更新
{
LinkList p = L;
int i=0;
while(p->next != NULL && loc >= i)
{
p = p->next;
i++;
}
p->data = new_element;
return true;
}
bool empty(LinkList L) //判断是否为空
{
if(L->data == 0 && L->next == NULL){
printf("is empty!\n");
return true;
}
return false;
}
bool clear(LinkList L) //清空表
{
LinkList p = L,q;
int i=0;
while(p->next != NULL)
{
p = p->next;
p->data = NULL;
L->data--;
i++;
}
L->next = NULL;
printf("total clear data is %4d",i);
return true;
}
LinkList destory(LinkList L) //销毁表
{
clear(L);
L = NULL;
printf("destory Successed!! \n");
return L;
}
void insert(LinkList L,int loc,int data) //插入数据
{
LinkList p=L,q;
int i = 0;
while(p->next != NULL && i<loc)
{
p = p->next;
i++;
}
q = p->next;
LinkList element = (LinkList)malloc(sizeof(Node));
element->data = data;
element->next = q;
p->next = element;
}
3、运行查看结果
LinkListMain.cpp
#include <stdio.h>
#include "LinkList.cpp"
int main()
{
LinkList L;
L = init(L);
empty(L);
for(int i=0;i<15;i++)
{
add(L,i);
}
empty(L);
printf("length is %d \n",length(L));
printf("the 10 is %d \n",get_int(L,10));
get_all(L);
del(L,3);
del(L,3);
del(L,3);
printf("length is %d \n",length(L));
get_int(L,10);
get_all(L);
printf("\n");
update(L,5,1000);
insert(L,3,33333);
get_all(L);
clear(L);
destory(L);
return 0;
}
运行结果:
init success!!
is empty!
length is 15
the 10 is 10
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
del success!
del success!
del success!
length is 12
0 1 2 6 7 8 9 10 11 12 13 14
0 1 2 33333 6 7 1000 9 10 11 12 13 14
total clear data is 13
total clear data is 0
destory Successed!!
--------------------------------
Process exited with return value 0
Press any key to continue . . .
链式表的优缺点
优点:新增和删除效率高
缺点:查找和修改效率低
这样,线性表的链式存储就了解完了,我们用自己写的这个来完成各小任务吧
题目1
有两个单链表LA和LB,其元素均为非递减有序排列,编写算法,将它们合并成一个单链表LC,要求LC也是非递减有序排列。例如,LA=(2,2,3),LB=(1,3,3,4),则LC=(1,2,2,3,3,4)。
算法分析
1、原来的两个都是非递减有序排列,也就是不需要我们排序了。
2、我们将下标从第一个结点开始,将LA和LB进行比较,小的先放入LC
,大的与另外的下一位比较,小的放入,依次进行下去。
3、最后将LA或者LB中多的放入LC中即可
实现
LinkList MergeLinkList(LinkList La,LinkList Lb,LinkList Lc)
{
LinkList pa,pb,pc;
pa = La->next;
pb = Lb->next;
Lc->data = La->data + Lb->data;
pc = Lc;
while(pa != NULL && pb != NULL)
{
if(pa->data <= pb->data)
{
pc->next = pa;
pc=pc->next;
pa = pa->next;
}else{
pc->next = pb;
pc=pc->next;
pb = pb->next;
}
}
if(pa != NULL)
pc->next = pa;
else
pc->next = pb;
return Lc;
}
算法性能分析
时间复杂度为:O(n),空间复杂度不考虑,题目有前提条件