数据结构 3.链表

顺序表(顺序存储):

        优点:可随机存取,存储密度高   

        缺点:要求大片连续空间,改变容量不方便

单链表(链式存储):

        优点:不要求大片连续空间,改变容量方便

        缺点:不可随机存取,要耗费一定空间存放指针

1.单链表

存储结构如下:

typedef struct Node{ //节点类型定义
    ElemType data;
    struct Node *next;
}Node,*LinkList;

 建立单链表:

typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList; 

//初始化一个空的单链表(不带头节点) 
bool InitList(LinkList &L) {
	L=NULL;
	return true;
}
//初始化一个空的单链表(带头节点) 
void InitList(LinkList &L) {
	L=(LNode*)malloc(sizeof(LNode));//分配一个头节点 
	L->next=NULL;
}

int main(){
	LinkList L; //声明一个指向单链表的指针 
	//初始化一个空的单链表
	InitList(L);
	..... 
}

插入(带头节点):

//在第i个位置插入元素e 
bool ListInsert(LinkList &L,int i,int e){
	if(i<1)
		return false;
	LNode *p; //p指向当前扫描到的结点
	int j=0; //当前p指向的是第几个结点
	p=L;
	while(p!=NULL && j<i-1){ //循环找到第i-1个结点 
		p=p->next;
		j++;
	}
	if(p == NULL) //i值不合法
		return false;
	LNode *s=(LNode*)malloc(sizeof(LNode));
	s->data=e;
	s->next=p->next;
	p->next=s;
	return true;
}

插入(不带头节点):

//在第i个位置插入元素e (不带头节点) 
bool ListInsert(LinkList &L,int i,int e){
	if(i<1)
		return false;
		
	if(i == 1){
		LNode *s=(LNode*)malloc(sizeof(LNode));
		s->data=e;
		s->next=L;
		L=s;
		return true;
	}
		
		
	LNode *p; //p指向当前扫描到的结点
	int j=1; //当前p指向的是第几个结点
	p=L;
	while(p!=NULL && j<i-1){ //循环找到第i-1个结点 
		p=p->next;
		j++;
	}
	if(p == NULL) //i值不合法
		return false;
	LNode *s=(LNode*)malloc(sizeof(LNode));
	s->data=e;
	s->next=p->next;
	p->next=s;
	return true;
}

指定结点后插操作:

​
//后插操作
bool InsertNextNode(LNode *p,int e){
	if(p==NULL)
		return false;
	LNode *s=(LNode*)malloc(sizeof(LNode));
	if(s==NULL) //内存分配失败
		return false;
	s->data=e;
	s->next=p->next;
	p->next=s;
	return true; 
​}

指定结点前插操作:

//前插操作
bool InsertPriortNode(LNode *p,LNode *s){
	if(p==NULL || s==NULL)
		return false;
	s->next=p->next;
	p->next=s;
	int temp = p->data;
	p->data=s->data;
	s->data=temp;
	return true; 
} 

删除结点(带头节点):

//在第i个位置删除元素 (带头结点)
bool ListDelete(LinkList &L,int i,int &e){
	if(i<1)
		return false;
	LNode *p; //p指向当前扫描到的结点
	int j=0; //当前p指向的是第几个结点
	p=L;
	while(p!=NULL && j<i-1){ //循环找到第i-1个结点 
		p=p->next;
		j++;
	}
	if(p == NULL) //i值不合法
		return false;
	if(p->next==NULL)//第i-1个结点之后无其他节点 
		return false;
	LNode *q=p->next;//q指向被删除的结点
	e=q->data;  //删除元素的值
	p->next=q->next;//将*q结点断开
	free(q);  //释放节点的存储空间 
	return true;
}

删除指定结点:

//删除指定结点p
bool DeleteNode(LNode *p){
	if(p==NULL)
		return false;
	LNode *q=p->next;
	p->data=p->next->data;
	p->next=q->next;
	free(q);
	return true;
} 

按位查找:

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

按值查找:

//按值查找
LNode * LocateElem(LinkList L,int e){
	LNode *p=L->next;
	while(p!=NULL && p->data!=e){
		p=p->next;
	} 
	return p;
} 

表长(带头节点):

//求表长
int Length(LinkList L){
	int len=0;
	LNode *p=L;
	while(p->next!=NULL){
		p=p->next;
		len++;
	}
	return len;
} 

尾插法建立单链表:

#include<stdio.h>
#include<malloc.h>

typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList; 

//初始化单链表(带头节点) 
void InitList(LinkList &L) {
	L=(LNode*)malloc(sizeof(LNode));//分配一个头节点 
	L->next=NULL;
}
//尾插法建立单链表
void ListTailInsert(LinkList &L){
	int x;
	L=(LinkList)malloc(sizeof(LNode));//建立头节点
	LNode *s,*r=L;
	scanf("%d",&x);
	while(x!=0){
		s=(LNode*)malloc(sizeof(LNode));
		s->data=x;
		r->next=s;
		r=s;
		scanf("%d",&x);
	} 
	r->next=NULL;
} 


int main(){
	LinkList L; //声明一个指向单链表的指针 
	//初始化一个空的单链表
	InitList(L);
	ListTailInsert(L);
	printf("number:");
	while(L->next!=NULL){
		L=L->next;
		printf("%d\t",L->data);
	}
	
}

结果:

12
13
14
15
0
number:12       13      14      15

头插法建立单链表:

#include<stdio.h>
#include<malloc.h>

typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList; 

//初始化单链表(带头节点) 
void InitList(LinkList &L) {
	L=(LNode*)malloc(sizeof(LNode));//分配一个头节点 
	L->next=NULL;
}

//头插法建立单链表
void ListHeadInsert(LinkList &L){
	LNode *s;
	int x;
	scanf("%d",&x);
	while(x!=0){
		s=(LNode*)malloc(sizeof(LNode));
		s->data=x;
		s->next=L->next;
		L->next=s;
		scanf("%d",&x);
	} 
}

int main(){
	LinkList L; //声明一个指向单链表的指针 
	//初始化一个空的单链表
	InitList(L);
	ListHeadInsert(L);
	printf("number:");
	while(L->next!=NULL){
		L=L->next;
		printf("%d\t",L->data);
	}
	
}

结果:

11
12
13
14
15
0
number:15       14      13      12      11

2.双链表

存储结构:

typedef struct DNode{
	ElemType data; //数据域 
	struct DNode *prior,*next; //前驱和后继指针 
}DNode,*DLinkList;

初始化:

//初始化双链表
bool InitDLinkList(DLinkList &L){
	L=(DNode*)malloc(sizeof(DNode));
	if(L == NULL)
		return false;
	L->prior = NULL;
	L->next = NULL;
	return true;
}

双链表的插入:

//双链表的插入
bool InsertNextDNode(DNode *p,DNode *s){
	if(p==NULL||s==NULL)
		return false;
	s->next=p->next; //将结点*s插入到*p之后 
	if(p->next != NULL)
		p->next->prior=s;
	s->prior=p;
	p->next=s;
	return true;
} 

双链表的删除:

//删除p结点的后继结点
bool DeleteNextNode(DNode *p){
	if(p==NULL)
		return false;
	DNode *q=p->next;
	if(q==NULL)
		return false;
	p->next=q->next;
	if(q->next!=NULL)
		q->next->prior=p;
	free(q);
	return true;
} 
//销毁操作
void Destroy(DLinkList &L){
	while(L->next!=NULL){
		DeleteNextNode(L);
	}
	free(L); //释放头节点 
	L=NULL;
} 

3.循环链表

循环单链表:

//循环单链表
typedef struct LNode{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList; 

//初始化一个循环单链表
bool InitList(LinkList &L){
	L=(LNode*)malloc(sizeof(LNode));
	if(L==NULL)
		return false;
	L->next=L;
	return true;
} 

//判断是否为空
bool isEmpty(LinkList L){
	return L->next == L;
} 
//判断结点p是否为循环单链表的表尾结点
bool isTail(LinkList L,LNode *p){
	return p->next == L;
} 

循环双链表:

//循环双链表
typedef struct DNode{
	ElemType data;
	struct DNode *prior,*next;
}DNode,*DLinkList; 
//初始化空的循环双链表
bool InitDLinkList(DLinkList &L){
	L=(DNode*)malloc(sizeof(DNode))
	if(L==NULL)
		return false;
	L->prior=L;
	L->next=L;
	return true;
} 
//判断是否为空
bool isEmpty(DLinkList L){
	return L->next == L;
} 
//判断结点p是否为循环双链表的表尾结点
bool isTail(DLinkList L,LNode *p){
	return p->next == L;
} 

4.静态链表

静态链表:定义一个较大的结构数组作为备用结点空间,当申请结点时,每个结点含有两个域,data域和next域,data域存放结点数据信息,next域不再是指针而是游标指示器

数组的方式实现的链表

优点:增删操作不需要大量移动元素

缺点:不能随机存取,只能从头节点开始依次往后查找,容量固定不可变

//静态链表
#define MaxSize 10 //静态链表的最大长度 
typedef struct {
	ElemType data;  //存储数据元素 
	int next; 		//下一个元素的数组下标 
}SLinkList[MaxSize]; 


#define MaxSize 10 //静态链表的最大长度 
struct Node{
	ElemType data;  //存储数据元素 
	int next; 		//下一个元素的数组下标 
};
typedef struct Node SLinkList[MaxSize];

5.顺序表和链表比较

存储结构

顺序表:

        优点:支持随机存取,存储密度高

        缺点:大片连续空间分配不方便,改变容量不方便

链表:

        优点:离散的小空间分配方便,改变容量方便

        缺点:不可随机存取,存储密度低

表长难以预估,经常增加或删除元素-----链表

表长可以预估,查询操作较多----顺序表

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值