线性表的链式存储实现(i-1节点,头指针)习题2.4 递增的整数序列链表的插入 (15分)习题2.5 两个有序链表序列的合并 (15分)

不要求逻辑上相邻的元素物理上也相邻
通过链来建立起数据元素之间的逻辑关系

**插入和删除不需要移动数据元素,**只需要修改链
但是访问序号为i的元素?
求线性表的长度?

//顺序表访问序号为i的元素和求线性表的长度

//访问下标为i的元素:L.Data[i]或PtrL->Data[i]
//线性表的长度:L.Last+1或者PtrL->Last+1//last是最后一个元素的下标
//如何存储
struct Node{
	ElementType Data;
	struct Node *Next;
}List;
List L,*PtrL;

在这里插入图片描述

//求表长
int Length(List *PtrL){
	List *p=PtrL;//p指向表的第一个节点
	int j=0;
	while(p){
		p=p->Next;//当前p指向第j个节点
		j++;
	}
	return j;
}
//查找
//按序号查找--------第k个
List *FindKth(int K,List *PtrL){
	List *p=PtrL;
	int i=1;
	while(p&&i<k){
		p=p->Next;
		i++;
	}
	if(i==k)
		return p;
	else 
		return NULL;
}
//按值查找Find
List *Find(ElementType X,List *PtrL){
	List*p=PtrL;
	while(p!=NULL&&p->Data!=x)
		p=p->next;
	return p;
}

在这里插入图片描述

//插入
//先构造一个新节点,用s指向
//再找到链表的第i-1个节点,用p指向
//然后修改指针 插入节点(p之后插入新节点是s)
List *Insert(ElementType X,int i,List *PtrL){
	List *p,*s;
	if(i==1){//新节点插入在表头
		s=(List*)malloc(sizeof(List));
		s->Data=X;
		s->Next=PtrL;
		return s;
	}
	p=FindKth(i-1,PtrL);
	//按序号查找--------第k个
	//List *FindKth(int K,List *PtrL){
	if(p==NULL){//没这个序号
		printf("参数i错误");
		return NULL;//第i-1个元素不存在,不能插入
	}else{
		s=(List*)malloc(sizeof(List));
		s->Data=X;
		s->Next=p->next;//新节点插入在第i-1个节点的后面
		p->Next=s;
		return PtrL;
	}
	
}

//malloc 向系统申请分配指定size个字节的内存空间。
//返回类型是 void* 类型。
//void* 表示未确定类型的指针。
//C,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针。--摘自百度百科 malloc函数
//删除(删除链表的第i(1<=i<=n)个位置上的结点)
List *Delete(int i,List *PtrL){
	List *p,*s;
	if(i==1){//删除的如果是第一个节点
		s=PtrL;//s指向第一个节点
		if(PtrL!=NULL)
			PtrL=PtrL->next;//从链表中删除
		else
			return NULL;
		free(s);
		return PtrL;
	}
	p=FindKth(i-1,PtrL);//查找第i-1个节点???????????
	if(p==NULL){
		printf("第%d个节点不存在",i-1);
		return NULL;
	}else if(p->Next==NULL){/??????????
		printf("第%d个节点不存在",i);
		return NULL;
	}else{
		s=p->Next;
		p->Next=s->Next;
		free(s);
		return PtrL;
	}
}
数据结构中,在单链表的第一个结点之前附设一个结点,它没有直接前驱,称之为头结点。
头结点的数据域可以不存储任何信息,头结点的指针域存储指向第一个结点的指针(即第一个元素结点的存储位置)。头结点的作用是使所有链表(包括空表)的头指针非空,并使对单链表的插入、删除操作不需要区分是否为空表或是否在第一个位置进行,从而与其他位置的插入、删除操作一致。

(这个更好的利用了头节点的性质)

这道题我自己刚开始写是没有头指针和头节点的区分,导致自己能运行对,但就是过不了(然后去找度娘),知道了头节点和头指针的区别。
在这里插入图片描述

头节点(在存数前有个只含指针的head)
头节点
有了头结点后,对在第一个元素结点前插入结点和删除第一个结点,其操作与对其它结点的操作统一了,这是头节点的优势。

总的来说,考察的是单链表的插入,基础题

typedef的用法
简单来讲,typedef的作用就是给某些类型定义别名,和#define类似,但是比#define更加灵活。

这里我暂时只遇到了两个使用场景:

第一处,定义普通数据类型
typedef int ElementType; // 所以包含这个语句的C文件中ElementType就代表了int
第二处,定义结构体和指针
struct Node;
typedef struct Node * PtrToNode; // 表示可以用PtrToNode类型代替指向结构体Node的指针类型
typedef PtrToNode List; // 表示List是PtrToNode的别名,其作用相同
typedef PtrToNode Position; // 同上
    List head = L;
    L=L->Next;

	 List p=(List)malloc(sizeof(List));
     p->Data=X;
     p->Next=NULL;

	
	    if(L==NULL){
         head->Next=p;
         return head;
     }

     List q=head;
     while(L->Data<X){
         q=L;
         L=L->Next;
         if(L->Next==NULL){//L->Next->Next
             L->Next=p;
             return head;
         }
     }
     
     p->Next=L;
     q->Next=p;
     return head;

浙大的数据结构题的单链表都带了一个头结点,以后遇到同类型的需要注意。
**都从各自的头结点开始,先指向下一位,**然后开始比较大小,把小的放前面,如果有一条比较完了,那么后面判断哪一条还未比较完,最后返回L。

List Merge( List L1, List L2 ){
	List a,b;
	a=L1->Next,b=L2->Next;	
	
	List c=(List)malloc(sizeof(List));
	List l=c;
	while(a&&b){
		if(a->Data>=b->Data){
			c->Next=b;
			c=b;
			b=b->Next;
		}else{
			c->Next=a;
			c=a;
			a=a->Next;
		}
	}
	if(a)c->Next=a;
	if(b)c->Next=b;
	L1->Next=NULL;
	L2->Next=NULL;
	return l;
}


为什么是 L1->Next = NULL ; 而不是直接 L1= NULL;
因为pta很多的链表都会自带一个头结点,
他给你的是自带头结点的链表,
如果直接L1=NULL,就相当于把头结点赋值空了,
所以就会答案错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值