《数据结构》学习记录(4):单链表和双链表的基本操作

一、单链表基本操作

1、定义单链表结点类型

#define elemType char

struct LinkNode     	   
{      
    elemType data;
    LinkNode *next;     //指向后继结点
};

2、创建单链表

  • 头插法建表:创建头结点,新结点插入到当前链表的表头
void CreateListF(LinkNode *&L, elemType a[], int n)
{    
    L = new LinkNode;
    L->next = nullptr;		//创建头结点,其next域置为NULL
    
    for (int i = 0;i < n;i++)		//循环建立数据结点
    {	
        LinkNode * s = new LinkNode;
        s->data = a[i];		//创建数据结点*s
        s->next = L->next;	//将*s插在原开始结点之前,头结点之后
        L->next = s;
    }
}
  • 尾插法建表:创建头结点,新结点插入到当前链表的表尾
void CreateListR(LinkNode *&L,elemType a[],int n)
{     
    L = new LinkNode;  //创建头结点
    LinkNode * r = L;	//r始终指向尾结点,开始时指向头结点
    for (int i = 0;i < n;i++)	//循环建立数据结点
    {	
        LinkNode * s = new LinkNode;
        s->data = a[i];	//创建数据结点*s
        r->next = s;	//将*s插入*r之后
        r = s;
    }
    r->next = nullptr;	//尾结点next域置为NULL
}

3、销毁线性表

void DestroyList(LinkNode *&L)//参数为头结点
{   
    LinkNode * p = L->next;    
    LinkNode * pre = L;//pre指向*p的前驱结点
    
    while (p)	//扫描单链表L
    {      
        delete pre;
        pre = p;		
        p = pre->next;
    }
    delete pre;     //循环结束时,p为NULL,pre指向尾结点,释放它
}

4、获取长度

int ListLength(LinkNode *L)//L为头结点
{
    int n = 0;
    LinkNode * p = L;	//p指向头结点,n置为0(即头结点的序号为0)
    
    while (p->next)
    {	
        n++;
        p=p->next;
    }
    return n;
}

5、遍历

void DispList(LinkNode *L)
{
    LinkNode * p = L->next;
    while (p)
    {	
        qDebug()<<" "<<p->data<<" ";
        p = p->next;
    }
}

6、求索引 index 处的元素

bool GetElem(LinkNode *L,int index,elemType &e) //L为头结点
{  
     int j = 0;
     LinkNode * p = L;

    while (j < index && p)
    {	
        j++;
        p=p->next;
    }
     
    if (p)
    {
        e = p->data;
        return true;
    }
    else
    {                    
        return false;
    }
}

7、在 index 处插入元素

bool ListInsert(LinkNode *&L,int index,elemType e)
{
    int j = 0;
    LinkNode *p = L;

    while (j < index - 1 && p)
    {	
        j++;
        p = p->next;
    }
    
    if (p)
    {
        LinkNode *s = new LinkNode;
        s->data = e;
        s->next = p->next;
        p->next = s;
        return true;
    }
    else
    {
        return false;
    }
}

8、删除 index 处的元素

bool ListDelete(LinkNode *&L,int index,elemType &e)
{
    int j = 0;
    LinkNode *p = L;
    
    while (j < index - 1 && p)
    {	
        j++;
        p = p->next;
    }
    if (!p)
        return false;
    else
    {	
        LinkNode *q = p->next;
        if (!q)
            return false;
        e = q->data;
        p->next = q->next;
        delete q;
        return true;
    }
}

二、双链表基本操作

1、定义双链表结点类型

#define elemType char
struct DLinkNode       	//双链表结点类型
{     
    elemType data;
    struct DLinkNode *prior;    	//指向前驱结点
    struct DLinkNode *next;     	//指向后继结点
};

2、建立双链表

  • 头插法建表
void CreateListF(DLinkNode *&L,elemType a[],int n)
{
    L = new DLinkNode;	//创建头结点
    L->prior = L->next = nullptr;	//前后指针域置为NULL
    for (int i = 0;i < n;i++)
    {	
        DLinkNode * s = new DLinkNode;
        s->data = a[i];		//创建数据结点*s
        s->next = L->next;
        if (L->next)
           L->next->prior = s;
        L->next = s;
        s->prior = L;
    }
} 
  • 尾插法建表
void CreateListR(DLinkNode *&L,elemType a[],int n)
{
    L = new DLinkNode;	//创建头结点
    DLinkNode * r = L;			//r始终指向尾结点,开始时指向头结点
    for (int i = 0;i < n;i++)
    {      
        DLinkNode * s = new DLinkNode;
        s->data = a[i];		//创建数据结点*s
        r->next = s;
        s->prior = r;	//将*s插入*r之后
        r = s;			//r指向尾结点
    }
    r->next=nullptr;
}

3、在 index 处插入元素

bool ListInsert(DLinkNode *&L,int index,elemType e)
{
    int j = 0;
    DLinkNode * p = L;	      	//p指向头结点,j设置为0
    while (j < index-1 && p)	//查找第i-1个结点
    {	
        j++;
        p=p->next;
    }      
    if (p)//找到第i-1个结点*p,在其后插入新结点*s
    {
        DLinkNode * s = new DLinkNode;
        s->data = e;		//创建新结点*s
        s->next = p->next;	//在*p之后插入*s结点
        if (p->next)	//若存在后继结点,修改其前驱指针
            p->next->prior = s;
        s->prior = p;
        p->next = s;
        return true;
    }
    else				
    {
        return false;
    }
}

4、删除第 index 个元素

bool ListDelete(DLinkNode *&L,int index,elemType &e)
{     
    int j = 0;   
    DLinkNode * p = L; 	 //p指向头结点,j设置为0
    
    while (j < index - 1 && p)	  	//查找第i-1个结点
    {	
        j++;
        p = p->next;
    }
    
    if (p)//找到第index-1个结点*p
    {
        DLinkNode * q = p->next;		//q指向第i个结点
        if (!q)
            return false;
        
        e = q->data;
        p->next = q->next;	//从双单链表中删除*q结点
        if (p->next)    	//修改其前驱指针
            p->next->prior = p;
        delete q;		   	
        return true;
    }
    else			   	
    {	    
        return false;
    }
}

三、两个算法示例

例1

void InterSect(LinkList *ha,LinkList *hb,LinkList *&hc)
{     
    LinkList * pa = ha->next;
    LinkList *pb = hb->next;
    hc = new LinkList;
    LinkList * r = hc;				 //r指向尾结点
    while (pa && pb)
    {
        if (pa->data < pb->data) 
            pa = pa->next;
        if (pa->data > pb->data) 
            pb = pb->next;
        if (pa->data == pb->data)           	                    //相同元素
        {	
            LinkList * s = new LinkList;      //复制结点
            s->data = pa->data;
            r->next = s;  
            r = s;
            pa = pa->next; 
            pb = pb->next;
        }
    }
    r->next = nullptr;
}

例2

void UnionList(SqList *LA,SqList *LB,SqList *&LC)
{     
    int i = 0,j = 0,k = 0;//i、j分别为LA、LB的下标,k为LC中元素个数
    LC = new SqList; 		//建立有序顺序表LC
    while (i < LA->length && j < LB->length)
    {	
        if (LA->data[i] < LB->data[j])
        {     
            LC->data[k] = LA->data[i];
            i++;
            k++;
        }
        else
        {     
            LC->data[k] = LB->data[j];
            j++;
            k++;
        }
    }   
    while (i < LA->length)		//LA尚未扫描完,将其余元素插入LC中
    {	
        LC->data[k] = LA->data[i];
        i++;
        k++;
    }
    while (j < LB->length)		//LB尚未扫描完,将其余元素插入LC中
    {	
        LC->data[k]=LB->data[j];
        j++;
        k++;
    }
    LC->length=k;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值