数据结构要点总结——03(下)线性表

在了解完线性表的顺序存储(顺序表)之后,我们接下来要说的就是线性表的链式存储,一般叫做链表(单链表),值得一提的是上一节中顺序表的操作还有一些如合并等,希望读者自行学习。

接下来我将从3个方面来介绍线性表的链式存储(单链表or线性链表):

1.概念

首先,线性表是一种逻辑概念,线性表的实现方式(存储方式)有两种,一种就是顺序存储,得到的表也叫顺序表;另一种就是链式存储,得到的表也就叫链表

线性链表的逻辑结构

一般情况下,每一个链表会有一个头指针(head),头指针指向首个结点,如果链表为空,那么头指针也肯定为空(可以作为判空条件)。

2.区别

这里详细再讲解一下两种存储的区别,如图为顺序存储的示意图,表中元素存储的物理地址是连续的。因此,在进行插入删除操作时需要对之后的元素全部进行位移操作(缺点)。但是这样可以随机存取。

顺序存储示意图

而链表的物理存储地址是不连续的,如图。链式存储的优点就是操作方便,不需要像顺序存储一样对之后的元素进行操作,缺点时地址不连续,地址利用率低,不可以随机存取。为了实现逻辑上的线性,链表中每一个节点需要有着一个指针域,存放后继节点的物理地址。(双链表还有一个指向前继节点的位置的指针域)

链式存储示意图

3.操作算法 

在这里提一嘴,我在网上看到在定义类的时候有使用typedef truct 的也有使用truct的,这里我简单说一下使用时的区别:

struct _x1

{

...

}x1;

是定义了类_x1和_x1的对象实例x1,使用时可以直接这样使用: x1.a=1   x1.b=2  

因为x1已经是一个实例化对象了

typedef struct _x2

{

...

} x2;

是定义了类_x2和_x2的类别名x2 ,在使用时还需要实例化一个对象,

x2  target;

target.a=1;

target.b=2;这样使用

具体区别的可以看http://t.csdnimg.cn/1vUX8的博客。

同上节一样,链表的创建首先需要定义一个结点对象,结点包含数据与和指针域,因此代码如下(这里不使用类C语言,而是直接使用C语言):

#include <stdio.h>
#include <stdlib.h>

// 定义链表结点结构
typedef struct LNode {
    int data;
    struct LNode* next;
}LNode,*LinkList;
//typedef <数据类型><别名> 
//LNode,*LinkList;这里等价于typedef struct LNode LNode  将结点这个数据类型重命名为LNode
// 以及 typedef struct LNode *LinkList   将指向结点的指针重命名为 LinkList


bool InitList(LinkList &L){//初始化链表 
    L = (LNode *)malloc(sizeof(LNode));//LNode *强调结点指针     LinkList强调指向的是一个链表(头指针) 
    if(L== NULL){
	return false;
    } //防止有脏数据 
    L->next=NULL; 
}

void PrintList(LinkList L){//打印链表 
	LNode *temp = L->next;
	while(temp!=NULL){
		printf("%d ",temp->data);
		temp=temp->next;
	}
	printf("\n");
}

bool InsertList(LinkList &L,int i,int x){//按位i插入数据x 
	if(i<1){
		return false;
	} 
	LNode *p;
	p=L;
	int j=0;
	while(p!=NULL && j<i-1){//侧面体现链表不可以随机存取,
	//顺序表可以根据结点大小,首结点位置和存放位置直接算出需要插入数据的位置 
		p=p->next;
		j++;
	}
	LNode *s = (LNode*)malloc(sizeof(LNode));//申请一个结点空间存放X 
	s->next=p->next;//先将s结点的后继改为p的后继  这一步和下一步可以颠倒 
	s->data=x;//再将x存放在s结点的数据域 
	p->next=s;//将p的后继改为s结点,s结点至此接入链表中,此步不可同第一步颠倒,
	//否则p->next被更改 链表会中断在s结点 
	return true;
}

bool DeleteList(LinkList &L,int i){//按位删除 
	if(i<1){
		return false;
	} 
	LNode *p;
	p=L;
	int j=0;
	while(p!=NULL && j<i-1){
		p=p->next;
		j++;
	}
	LNode *temp =  p->next;
	p->next=temp->next;
	return true;
}

LNode* GetInit(LinkList L,int i){//按位查找 
	if(i<1){
		return NULL;
	} 
	LNode *p;
	p=L;
	int j=0;
	while(p!=NULL && j<=i-1){
		p=p->next;
		j++;
	}
	printf("%d",p->data);
	return p;
} 

bool ChangeInit(LinkList L,int i,int x){//按位修改 
	if(i<1){
		return false;
	} 
	LNode *p;
	p=L;
	int j=0;
	while(p!=NULL && j<=i-1){
		p=p->next;
		j++;
	}
	p->data=x;
	return true;
}

int main(){//测试案例 
	LinkList L;
	InitList(L);
	InsertList(L,1,1);
	InsertList(L,2,2);
	InsertList(L,3,3);
	InsertList(L,4,4);
	InsertList(L,5,5);
	InsertList(L,6,6);
	DeleteList(L,4);
	ChangeInit(L,4,99);
	PrintList(L);
	GetInit(L,4); 
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值