数据结构01单链表和顺序表

本文深入探讨了链表和顺序表这两种基本数据结构。详细介绍了单链表、循环链表、双向链表的定义、操作函数及其实现,包括初始化、插入、删除等关键功能。同时,讲解了顺序表及其动态扩容的原理与实现细节。

1单链表

1.1单链表介绍

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结
点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位
置),元素就是存储数据的存储单元,指针就是连接每个结点的地址
数据。定义如下:
typedefstructNode
{
intdata;
structNode*next;
}Node,*List;

1.1.1主要函数

voidInitList(Listplist);//初始化单链表
boolInsert_head(Listplist,intval);//头插法
boolInsert_tail(Listplist,intval);//尾插法
boolInsert_pos(Listplist,intpos,intval);//pos 位置插入
Node*Search_pre(Listplist,intkey);//查找 key 的前驱
boolDelete(Listplist,intkey);//删除 key 这个结点
boolIsEmpty(Listplist);//是否为空
voidDestroy(Listplist);//摧毁函数(如果有动态开辟内存)
intGetLength(Listplist);//得到单链表的长度
voidShow(Listplist);//打印单链表
voidReverse(Listplist);//逆置单链表

1.1.2相关习题

1、两个有序单链表的合并
Node* Merge_list(Node *q1, Node *q2);

Node* MergeList(List plist1,List plist2)
{
	Node *p1 = plist1->next;
	Node *p2 = plist2->next;
	Node *newHead = NULL;//newHead合并之后新的头结点
	if(p1->data < p2->data)
	{
		newHead = plist1;
	}
	else 
	{
		newHead = plist2;
	}
	Node *tmpHead = newHead;
	while(p1 != NULL && p2 != NULL) 
	{
		if(p1->data >p2->data )
		{
			tmpHead  ->next =p2 ;
			tmpHead  =tmpHead  ->next ;
			p2=p2->next ;
		}
		else//if(p1 ->data <p2->data )
		{
			tmpHead  ->next =p1;
			tmpHead =tmpHead  ->next ;
			p1=p1->next ;
		}

		if(p1!=NULL  )
		{
			tmpHead->next =p1 ;
		}
		if(p2!=NULL )
		{
			tmpHead ->next =p2;
		}
	}
	return newHead ;
}

2、两个单链表是否相交,如果相交求他的交点是?
bool IsCut(list plist,list qlist);
Node *FirstNode(list plist,list qlist);

void CreateCut(List plist1,List plist2)
{
	plist1->next->next = plist2->next->next->next;
}

bool IsCut(List plist1,List plist2)
{
	int len1 = GetLength(plist1);
	int len2 = GetLength(plist2);
	Node *plong = plist1;
	Node *pshort = plist2;
	int len = len1-len2;
	if(len < 0) 
	{
		plong = plist2;
		pshort = plist1;
		len = len2-len1;
	}
	//plong肯定指向长的   pshort 
	//len > 0
	for(int i = 0;i < len;i++)
	{
		plong = plong->next;
	}
	while(plong != NULL && pshort != NULL && plong != pshort)
	{
		plong = plong->next;
		pshort = pshort->next;
	}
	if(plong == pshort && plong != NULL)
	{
		return true;
	}
	return false;
}

Node* IsCutNode(List plist1,List plist2)
{
	int len1 = GetLength(plist1);
	int len2 = GetLength(plist2);
	Node *plong = plist1;
	Node *pshort = plist2;
	int len = len1-len2;
	if(len < 0) 
	{
		plong = plist2;
		pshort = plist1;
		len = len2-len1;
	}
	//plong肯定指向长的   pshort 
	//len > 0
	for(int i = 0;i < len;i++)
	{
		plong = plong->next;
	}
	while(plong != NULL && pshort != NULL && plong != pshort)
	{
		plong = plong->next;
		pshort = pshort->next;
	}
	if(plong == pshort && plong != NULL)
	{
		return plong;
	}
	return NULL;
}

3、单链表倒数第 K 个结点
Node *listnode_lastk(list plist,int k);

Node *LastK(List plist,int k)
{
	if(k < 0 || plist == NULL)
	{
		return NULL;
	}
	Node *p1 = plist;
	Node *p2 = plist;
	while(k-1 > 0)
	{
		if(p1->next != NULL) 
		{
			p1 = p1->next;
			--k;
		}
		else
		{
			return NULL;
		}
	}
	while(p1->next != NULL)
	{
		p1 = p1->next;
		p2 = p2->next;
	}
	return p2;
}
void InitList(List plist)//初始化单链表
{
	assert(plist != NULL);
	plist->next = NULL;
}

static Node *GetNode(int val)
{
	Node* pGet = (Node *)malloc(sizeof(Node));
	assert(pGet != NULL);
	pGet->data = val;
	pGet->next = NULL;
	return pGet;
}

bool Insert_head(List plist,int val)//头插法
{
	Node *pGet = GetNode(val);
	pGet->next = plist->next;
	plist->next = pGet;
	return true;
}

bool Insert_tail(List plist,int val)//尾插法
{
	Node *cur = plist;//指向头结点  依赖前驱信息的
	while(cur->next != NULL)
	{
		cur = cur->next;
	}
	Node *pGet = GetNode(val);
	cur->next = pGet;
	return true;
}

bool Insert_pos(List plist,int pos,int val)//pos 位置插入
{
	if(pos < 0 || pos > GetLength(plist))
	{
		return false;
	}
	Node *cur = plist;
	for(int i = 0;i <= pos-1;i++)
	{
		cur = cur->next;
	}
	Node *pGet = GetNode(val);
	pGet->next = cur->next;
	cur->next = pGet;
	return true;
}

Node *Search_pre(List plist,int key)//查找 key 的前驱
{
	if(IsEmpty(plist))
	{
		return NULL;
	}
	Node *cur = plist;
	while(cur->next != NULL)
	{
		if(cur->next->data == key)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

bool Delete(List plist,int key)//删除 key 这个结点
{
	Node *p = Search_pre(plist,key);
	if(p == NULL)
	{
		return false;
	}
	Node *pDel = p->next;//删除的节点
	p->next = pDel->next;
	free(pDel);
	pDel = NULL;
	return true;
}

bool IsEmpty(List plist)//是否为空
{
	if(plist == NULL || plist->next == NULL)
	{
		return true;
	}
	return false;
}

void Destroy(List plist)//摧毁函数(如果有动态开辟内存)
{
	Node *pDel = NULL;
	while(plist->next != NULL)
	{
		pDel = plist->next;
		plist->next = pDel->next;
		free(pDel);
	}
	pDel = NULL;
}
//得到单链表的长度
int GetLength(List plist)
{
	int count = 0;
	Node *pCur = plist->next;
	while(pCur != NULL)
	{
		count++;
		pCur = pCur->next;
	}
	return count;
}

//打印单链表
void Show(List plist)
{
	Node *pCur = plist->next;
	while(pCur != NULL)
	{
		printf("%d ",pCur->data);
		pCur = pCur->next;
	}
	printf("\n");
}
Node* Reverse1(List plist)//反转
{
	Node *prev = NULL;
	Node *reverHead = NULL;
	Node *cur = plist;
	while(cur != NULL)
	{
		Node *curNext = cur->next;
		if(curNext == NULL)
		{
			reverHead = cur;
		}
		cur->next = prev;//NULL
		prev = cur;
		cur = curNext;
	}
	return reverHead;
}
void Reverse2(List plist)//头插法逆置
{
	Node *cur = plist->next;
	plist->next = NULL;
	while(cur != NULL)
	{
		Node *curNext = cur->next;
		cur->next = plist->next;
		plist->next = cur;
		cur = curNext;
	}
}

1.2循环单链表

typedef struct CNode
{
int data;
struct CNode *next;
}CNode,*CList;

1.2.1主要函数

void InitList(CList plist);//初始化
bool Insert_head(CList plist,int val);//头插法
bool Insert_tail(CList plist,int val);//尾插法
CNode *Search_pri(CList plist,int key);//查找前驱
bool Delete(CList plist,int key);//删除
bool IsEmpty(CList plist);//是否为空
void Destroy(CList plist);//摧毁
int GetLength(CList plist);//得到长度
void Show(CList plist);//显示函数
1、判断是否有环?环的入口点?计算环的长度?
bool Isloop(Clist plist);
Node *FindEtrance(Clist plist);
int lengthOfLoop(Node *plist1);

bool Isloop(Node *plist1)
{
	Node *pf=plist1 ;
	Node *ps=plist1 ;
	while(pf!=NULL &&pf->next !=NULL )
	{
		pf=pf->next ->next ;
		ps=ps->next ;
		if(pf ==ps )
		{
			break ;
		}
		if(pf==NULL ||ps==NULL )
		{
			return true;
		}
	}
	return true;
}
Node *FindEnte(Node *plist1)
{
	Node *pf=plist1 ;
	Node *ps=plist1 ;
	Node *ptmp=NULL ;
	while(pf!=NULL &&pf->next !=NULL )
	{
		pf=pf->next ->next ;
		ps=ps->next ;
		if(pf ==ps )
		{
			ptmp =pf;
		}
		if(pf==NULL ||ps==NULL )
		{
			return NULL ;
		}
	}
	ps=plist1 ;
	while(pf!=ps)
	{
		pf=pf->next ;
		ps=ps->next ;
	}
	return ps;
}
int lengthOfLoop(Node *plist1)//入口 也算
{
	Node *pf=plist1 ;
	Node *ps=plist1 ;
	Node *ptmp=NULL ;
	int count =1;
	while(pf!=NULL &&pf->next !=NULL )
	{
		pf=pf->next ->next ;
		ps=ps->next ;
		if(pf ==ps )
		{
			//count++;
			break;
		}
		if(pf==NULL ||ps==NULL )
		{
			return NULL ;
		}
	}
	ps=ps->next ;
	while(pf!=ps)
	{
		//pf=pf->next ;
		ps=ps->next ;
		count ++;
	}
	return count;
}

1.2.2实现

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Clist.h"
void InitList(CList plist)//初始化
{
	assert(plist != NULL);
	plist->next = plist;
}
static CNode *GetNode(int val) 
{
	CNode *pGet = (CNode *)malloc(sizeof(CNode));
	assert(pGet != NULL);
	pGet->next = NULL;
	pGet->data = val;
	return pGet;
}
bool Insert_head(CList plist,int val)//头插法
{
	CNode *pGet = GetNode(val);
	pGet->next = plist->next;
	plist->next = pGet;
	return true;
}
//bool Insert_tail(CList plist,int val)//尾插法
//{
//
//}
//CNode *Search_pri(CList plist,int key)//查找前驱
//{
//
//}
//bool Delete(CList plist,int key)//删除
//{
//
//}
bool IsEmpty(CList plist)//是否为空
{
	return plist->next == plist;
}
void Destroy(CList plist)//摧毁
{
	CNode *p = NULL;
	while (plist->next != plist)
	{
		p = plist->next;
		plist->next = p->next;
		free(p);
	}
	p = NULL;
}
int GetLength(CList plist)//得到长度
{
	int count = 0;
	CNode *p = plist->next;
	while(p != plist)
	{
		count++;
		p = p->next;
	}
	return count;
}
void Show(CList plist)//显示函数
{
	CNode *p = plist->next;
	while(p != plist)
	{
		printf("%d ",p->data);
	}
	printf("\n");
}

1.3双向链表

对于循环单链表来说,它的每个数据结点中都有两个指针,分别
指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,
都可以很方便地访问它的前驱结点和后继结点。
typedef struct DNode
{
int data;
struct DNode *next;
struct DNode *prio;
}DNode,*DList;

1.3.1主要函数

void InitList(DList plist);
bool Insert_head(DList plist,int val);
bool Insert_tail(DList plist,int val);
DNode *Search_pri(DList plist,int key);
bool Delete(DList plist,int key);
bool IsEmpty(DList plist);
void Destroy(DList plist);
int GetLength(DList plist);
void Show(DList plist);

1.3.2实现

#include"Dlist.h"
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
void InitList(DList plist)
{
	assert (plist !=NULL );
	plist ->prev =NULL ;
	plist ->next =NULL ;
}
static DNode *GetNode(int val)
{
	DNode * pGet = (DNode *)malloc(sizeof(DNode));
	assert(pGet != NULL);
	pGet->data = val;
	pGet->next = NULL;
	pGet->prev =NULL ;
	return pGet;
}
bool Insert_head(DList plist,int val)
{
	DNode *pGet=GetNode(val);
	pGet ->next =plist ->next ;
	if(pGet ->next !=NULL )//第一次插入时为空不要这句话
	{
		pGet ->next ->prev =pGet ;
	}
	plist ->next =pGet ;
	pGet ->prev =plist ;
	return true;

}
bool Insert_tail(DList plist,int val)
{
	DNode *p=plist ;
	while(p->next !=NULL )
	{
		p=p->next ;
	}
	DNode *pGet=GetNode(val);
	pGet->next =NULL ;
	pGet ->prev =p;
	return true;
}
DNode *Search_pri(DList plist,int key)
{
	DNode *p=plist ;
	while(p->next !=NULL )
	{
		if(p->data ==key)
		{
			return p->prev ;
		}
	}
	return NULL ;
}
bool Delete(DList plist,int key)//删除最后一个要注意插入第一个要注意
{
	DNode *p=Search_pri (plist ,key );
	if(p == NULL)
	{
		return false;
	}
	DNode *pDel=p->next ;
	p->next =pDel ->next ;
	if(pDel ->next ==NULL )
	{
		pDel ->next ->prev =p;
	}
	free(pDel);
	pDel = NULL;
	return true;
}
bool IsEmpty(DList plist)
{
	return plist ->next ==NULL ;
}
void Destroy(DList plist)
{
	DNode *p=NULL ;
	while(plist ->next !=NULL )
	{

	}
}
int GetLength(DList plist)
{

}
void Show(DList plist)
{
	DNode *p=plist ;
	while(p!=NULL )
	{
		printf ("%d\n",p->data );
		p=p->next ;
	}
	printf ("\n");
}

2 顺序表

2.1图解定义

#pragmaonce
#defineSIZE10
typedefstructSqlist
{
intelem[SIZE];
intlength;
}Sqlist,*PSqlist;
在这里插入图片描述

2.2主要函数

voidInitSqlist(PSqlistPsq);//初始化
boolInsert(PSqlistPsq,intpos,intval);//在 pos 位置插入 val 值
intSearch(PSqlistPsq,intpos,intkey);//查找 key 值
boolDeletePos(PSqlistPsq,intpos,intrtv);//删除 pos 位置的值
boolDelete(PSqlistPsq,intpos,intkey);//删除一个 key 值
boolGetElem(PSqlistPsq,intpos,int
rtv);//不能用下标(-2 不好弄)
intGetLength(PSqlistPsq);
voidClear(PSqlistPsq);
voidDestory(PSqlistPsq);
voidShow(PSqlistPsq);

#include<stdio.h>
#include<assert.h>
#include"sqlist.h"
void InitSqlist(PSqlist Psq)//初始化
{
	assert(Psq!=NULL );
	if(Psq==NULL )
	{
		return;
	}
	Psq->usedsize =0;
}
static bool IsFull(PSqlist Psq)//判断有没有满
{
	return Psq->usedsize ==SIZE ;//返回表达式的真假
}
bool Insert(PSqlist Psq,int pos ,int val)//在 pos 位置插入 val 值
{
	assert(Psq!=NULL );
	//pos位置判断
	if(pos <0||pos > Psq->usedsize||IsFull(Psq ) )
	{
		return false ;
	}
	for(int i=Psq ->usedsize -1;i>=pos;i--)
	{
	    Psq ->elem [i+1]=Psq ->elem [i];
	}
	Psq ->elem [pos]=val;
	Psq ->usedsize ++;
	return true ;
}
bool Isempty(PSqlist Psq)
{
	return Psq ->usedsize ==0;//==0就是空的
}
int Search(PSqlist Psq,int pos,int key)//查找 key 值,从pos 位置开始查找key
{
	assert(Psq!=NULL );
	if(pos <0||pos>=Psq ->usedsize||Isempty (Psq) )
	{
		return false;
	}
	int i=pos;
	for(int i=pos;i<Psq ->usedsize ;i++)
	{
		if(key==Psq ->elem [i])
		{
			return i ;
		}
	}
	return -1;
}

bool DeletePos(PSqlist Psq,int pos,int *rtv)//删除 pos 位置的值
{
	//assert(Psq!=NULL &&rtv !=NULL );
	if(pos <0||pos>=Psq ->usedsize||Isempty (Psq) )
	{
		return false;
	}
	if(rtv != NULL)//rtv有效
	{
		*rtv = Psq->elem[pos];//把POS的值放在rtv里
	}
	for(int i=pos;i<Psq ->usedsize -1;i++)
	{
		Psq ->elem [i]=Psq ->elem [i+1];//往前挪
	}
	Psq ->usedsize --;
	return true;
}
bool Delete(PSqlist Psq,int pos,int key)//删除一个 key 值
{
	int index=Search ( Psq ,pos ,key );//找到值
	if(index ==-1)
	{
		return false ;
	}
	return DeletePos (Psq ,index ,NULL);//删除值
}

bool GetElem(PSqlist Psq,int pos,int *rtv)//得到pos位置的值
{
	if(pos <0||pos>=Psq ->usedsize||Isempty (Psq) )
	{
		return false;
	}
	*rtv =Psq ->elem [pos];
	return true ;
}

int GetLength(PSqlist Psq)
{
	return Psq->usedsize ;
}

void Clear(PSqlist Psq)
{
	Psq ->usedsize =0;
}

void Destory(PSqlist Psq);

void Show(PSqlist Psq)
{
	for(int i=0;i<Psq ->usedsize;i++)
	{
		printf("%d ",Psq ->elem [i]);
	}
	printf("\n");
}

2.3倍数扩容

2.3.1定义

#pragmaonce
#defineINIT_SIZE10
typedef struct DSqlist
{
int*elem;//存储数据的内存
intusedsize;//有效数据个数
intsize;//总单元数
}DSqlist,*PDSqlist;

2.3.2主要函数

voidInitList(PDSqlistpsq);
boolInsert(PDSqlistpsq,intpos,intval);
intSearch(PDSqlistPsq,intpos,intkey);//查找 key 值
boolDeletePos(PDSqlistPsq,intpos,int*rtv);//删除 pos 位置的值
boolDelete(PDSqlistPsq,intpos,intkey);//删除一个 key 值
voidClear(PDSqlistpsq);
voidDestroy(PDSqlistpsq);
voidShow(PDSqlistpsq);

2.3.3实现

#include"Dsqlist.h"
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
void InitList(PDSqlist psq)//初始化
{
	assert(psq !=NULL );
	psq->elem =(int *)malloc (sizeof (int )*INIT_SIZE );
	assert(psq->elem !=NULL );
	psq->usedsize =0;
	psq->size =INIT_SIZE ;
}
static bool isFull(PDSqlist psq)
{
	/*if(psq ->usedsize ==psq ->size )
	{
		return true ;
	}
	return false ;*/
	return psq ->usedsize ==psq ->size;
}
static void Inc(PDSqlist psq)//扩容
{
	int *p =(int *)realloc (psq ->elem ,psq->size *sizeof (int )*2 );
	if(p!=NULL )
	{
		psq->elem =p;
	}
	psq->size *=2;
}
bool Insert(PDSqlist psq,int pos,int val)//插入
{
	if(isFull (psq ))
	{
		Inc (psq );
	}
	for(int i=psq ->usedsize -1;i>=pos;i--)
	{	
	    psq ->elem [i+1]=psq ->elem [i];//往前挪
	}
	psq ->elem [pos]=val;
	psq ->usedsize ++;
	return true ;

}
bool Isempty(PDSqlist psq)
{
	return psq ->usedsize ==0;
}
int Search(PDSqlist psq,int pos,int key)//查找 key 值
{
	assert(psq!=NULL );
	if(pos <0||pos>=psq ->usedsize||Isempty (psq) )
	{
		return false;
	}
	int i=pos;
	for(int i=pos;i< psq ->usedsize ;i++)
	{
		if(key==psq ->elem [i])
		{
			return i ;
		}
	}
	return -1;
}

bool DeletePos(PDSqlist Psq,int pos,int *rtv)//删除 pos 位置的值
{
	if(pos <0||pos>=Psq ->usedsize||Isempty (Psq) )
	{
		return false;
	}
	if(rtv != NULL)
	{
		*rtv = Psq->elem[pos];
	}
	for(int i = pos;i < Psq->usedsize-1;i++)
	{
		Psq->elem[i] = Psq->elem[i+1];
	}
	Psq->usedsize--;
	return true;
}

bool Delete(PDSqlist Psq,int pos,int key)//删除一个 key 值
{
	int index=Search ( Psq ,pos ,key );
	if(index ==-1)
	{
		return false ;
	}
	return DeletePos (Psq ,index ,NULL);
}

void Clear(PDSqlist psq)
{
	psq->usedsize =0;
	psq->size = 0;
}

void Destroy(PDSqlist psq)
{
	free(psq->elem );
	psq->elem =NULL ;
	psq->usedsize =0;
	psq ->size =0;
}

void Show(PDSqlist Psq)
{
	for(int i=0;i<Psq ->usedsize;i++)
	{
		printf("%d ",Psq ->elem [i]);
	}
	printf("\n");
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我的sun&shine

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值