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,intrtv);//不能用下标(-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");
}
本文深入探讨了链表和顺序表这两种基本数据结构。详细介绍了单链表、循环链表、双向链表的定义、操作函数及其实现,包括初始化、插入、删除等关键功能。同时,讲解了顺序表及其动态扩容的原理与实现细节。
442

被折叠的 条评论
为什么被折叠?



