数据结构线性表之链式存储-------单链表及其基本操作

单链表(线性表链式存储)

1.单链表初始化(结点存放数据元素和下个结点指针)

1.1定义一个带头结点的单链表:

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

typedef struct LNode{
	int data;
	struct LNode* next;
}LNode,*link_list;//强调是单链表用linklist,强调是节点用LNode*

bool InitList ( link_list &L ){//链表初始化
	L = ( LNode* )malloc(sizeof(LNode) );//申请一个头结点空间
	if( L==NULL )//内存不足,分配失败
		return false;
	L->next==NULL;//头结点之后没有节点
	return true;
}

bool isEmpty( link_list L){//判断链表是否为空
	return (L == NULL);
}
int main( int argc, char const*argv[] )
{}

1.2定义一个不带头结点的单链表

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

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

bool InitList( LinkList &L ){
	L = NULL;//头指针不指向任何结点,空表
	return true;
}

2.单链表的插入

在这里插入图片描述

2.1按位序插入

2.1.1按位序插入(带头结点)

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

bool InsertList (LinkList &L, int i, int e){//单链表L第i位置插入元素e
	if( i<1 )//位置非法
		return false;
	LNode* p = L;//指针p指向当前扫描到的结点,L为头结点 
	int j = 0;//j为扫描到第几个结点
	if( p!=NULL && j<i-1 ){//扫描结点不为空且没有到i位置
		p = p->next;
		j++;
	}
	if( p == NULL )//i值不合法,如共有三个元素,要往第十个位置插
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode) );//申请空节点存元素e
	s->data = e;
	s->next = p->next;//先连后断
	p->next = s;
	return true;
}

2.1.2按位序插入(不带头结点)

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

typedef struct LNode{
	int data;
	struct LNode* next;
}LNode, *LinkList;  //LNode*与LinkList相同

//不带头节点的单链表按位序插入
bool Insertlist( 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;      //新结点指针s->next指向头指针L指的结点,即原本的第一个结点
		L = s;            //头指针指向新插入的第一个结点
		return true;
	}
	LNode* p;
	p = L;
	int j = 1;
	while( p!=NULL && j<i-1 ){
		j++;
		p = p->next;
	}
	if(p==NULL)
		return false;
	LNode*s = (LNode*)malloc( sizeof(LNode) );
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}
int main(){
}

2.2指定结点的后插操作

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

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

//指定结点的后插操作
bool InsertNextNode( LNode*p, int e ){
	if(p==NULL)//指定结点为空时返回false
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode) );//申请空结点存传入值e
	if(s==NULL)//申请空间失败
		return false;
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

2.3指定结点的前插操作

还有一种思路是:传入头结点,遍历找到前插位置的前驱结点,再进行后插。

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

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

情况一://给定值情况(需要申请内存)
bool InsertPriorNode ( LNode* p, int e ){//给定值情况
	if( p==NULL )//如果指定结点为空则错误
		return false;
	LNode* s = (LNode*)malloc( sizeof(LNode) );
	if(s==NULL)//分配内存失败
		return NULL;
	s->next = p->next;
	p->next = s;
	s->data = p->data;//偷天换日
	p->data = e;
	return true;
}

情况二://直接给指针(需要定义临时变量)

bool InsertPriorNode ( 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;
}

3.单链表的结点删除操作

3.1按位序删除

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

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

传入链表(即链表的头指针)、指定位置、e返回被删值
bool ListDelete ( LinkList &L, int i, int e ){
	if(i<1)
		return false;
	LNode* p = L;//定义扫描指针
	int j = 0;//记录位置
	while( p!=NULL && j<i-1 ){//删第i个,找第i-1个
		p = p->next;
		j++;
	}
	if(p==NULL)//i值非法
		return false;
	if(p->next == NULL)//指定位置为空
		return false;
	LNode*q = p->next;//定义一个指针指向位置i,即指定删除位置
	e = q->data;
	p->next = q->next;
	free(q);//不要忘记释放删除的结点
	return true;
}

3.2删除指定结点

此段代码有bug,应该从头遍历找到指定结点的前驱结点

bool LinkListDelete( LNode*p ){
	if( p==NULL )
		return false;
	LNode* q = p->next;
	p->data = p->next->data;//p->next可能为NULL
	p->next = q->next;
	free(q);
}

4.单链表的查找操作

在这里插入图片描述

4.1按位查找

#include<stdio.h>

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

//按位查找
LNode* GetElemlink ( LinkList L, int i ){
	if( i<0 )//i<0位置不合法
		return NULL;
	LNode*p = L;//定义和头指针指向一样结点的指针
	int j = 0;
	while( p->next != NULL && j<i ){
		p = p->next;
		j++;
	}
	return p;
}

4.2按值查找

//按值查找
LNode* LocateElemlink ( LinkList L, int e ){//返回值是指向结点的指针
	LNode* p = L->next;//定义指向第一个结点的指针,头结点指的那个结点
	while( p != NULL && p->data != e )链表非空且未找到给定值
		p = p->next;
	return p;返回p
}

4.3求链表长度

#include<stdio.h>

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

int lenthlink (LinkList L){
	int len = 0;
	LNode*p = L;//定义指针
	while( p->next != NULL ){//不为空就加一
		p = p->next;
		len++;
	}
	return len;
}

5.单链表的建立

在这里插入图片描述

5.1尾插法

在这里插入图片描述

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

typedef struct LNode{
	int data;
	struct LNode*next;
}LNode,* LinkList;
//尾插法建立链表
LinkList List_Tailinsert( LinkList &L ){//注意返回值
	int x;//局部变量存输入
	L = (LinkList)malloc( sizeof(LNode) );//头指针申请头结点
//	LNode*s, *r = L;此处写法有误,指针s未初始化
	LNode*s = L, *r = L;//这样写才对
	scanf("%d",&x);
	while( x != 9999 ){
		s = (LNode*)malloc(sizeof(LNode) );//给存入数据申请空间
		s->data = x;
		r->next = s;
		r = s;//尾指针保持指向最后一位
		scanf("%d",&x);
	}
	r->next = NULL;//最后结点指向NULL
	return L;
}

5.2头插法

对头结点的后插操作
应用:对链表的逆置(1.原地逆置 2.新建链表)

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

typedef struct LNode{
	int data;
	struct LNode*next;
}LNode, *LinkList;
//头插法建立链表
LinkList List_headinsert ( LinkList &L ){//传入,传出都是指针
	LNode*s;
	int x;
	L = (LinkList)malloc(sizeof(LNode) );//创建头结点
	L = NULL;//初始化头指针
	scanf("%d",&x);
	while( x != 9999 ){
		s = (LNode*)malloc(sizeof(LNode) );//创建新结点
		s->data = x;
		s->next = L->next;
		L->next = s;//将新结点插入表中,L为头指针
		scanf("%d",&x);
	}
	return L;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值