线性表--循环链表的简单知识

循环链表核心思想和单向链表其实一样,数据结构没变,就是她的尾节点又指向了头结点,饶了个圈,循环了一下。

和双向链表不一样,循环其实就尾节点算有程序上的前驱后继而已。

尾指针循环链表就是在原基础上又添加了尾指针指向尾节点,在合并的时候方便,知道了尾指针能得到尾节点和头结点。

我只写了和单向链表不一样的部分,注释也只是注释了和单向链表不一样的地方。所以显得(反正单向里面都有了)

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

typedef int datatype;

typedef struct Node {
	datatype data;
	struct Node *pNext;
}Node, *pNode;

//=============================
//头指针循环链表
void Init(pNode &pHead);//初始化  
void CreateTail(pNode pHead);//尾插法建表  
bool isEmpty(pNode pHead);//判断是否为空  
int length(pNode pHead);//求链表长度  
void Traverse(pNode pHead);//遍历 
//=================================
//尾指针循环链表
void CreateTail1(pNode pHead,pNode &tailpointer);
 //void Merge1(pNode &Ahead,pNode &Bhead,pNode tailpointerA,pNode tailpointerB);//合并俩链表 
//==============================

void Init(pNode &pHead) {
	pHead  = (pNode)malloc(sizeof(Node));
	if(!pHead ) {
		printf("failed!\n");
		exit(-1);
	}
	pHead->pNext = pHead; //这里和单向链表不一样,形成一个圈
}
//===============================================
void CreateTail(pNode pHead) {
	printf("输入节点个数:");  
    int n,i = 0;  
    scanf("%d",&n);  
    pNode pTail = pHead ; 
    while( i < n) {  
        datatype item;  
        printf("请输入节点值:");  
        scanf("%d",&item);  
        pNode pNew = (pNode)malloc(sizeof(Node));
        pNew->data = item;  
          //这里和单向链表不一样
        pTail->pNext = pNew;//把pNew给尾节点做后继  
        pNew->pNext = pHead;//pNew指向了头  
        pTail = pNew;//让pNew做尾节点  
          
        i++;  
    }  
    return ;  
	
}
//=====================================  
//判断是否为空  
bool isEmpty(pNode pHead) {  
    if(pHead == pHead->pNext ) { //这里和单向链表不一样,因为循环嘛
        printf("空!\n");  
        return true;  
    }else  
        return false;  
}  
  
//=====================================  
//求链表长度  
int length(pNode pHead) {  
    pNode p = pHead->pNext;  
    int count = 0;  
    if(isEmpty(pHead ))  
        return count;
    while(p != pHead ) {   //这里和单向链表不一样
        count++;  
        p = p->pNext ;
    }  
    return count;
}  
//=====================================  
//遍历  
void Traverse(pNode pHead) {  
    if(isEmpty(pHead)) {  
        return ;//空表就没啥遍历可言了  
    }  
    pNode p = pHead->pNext;  
    while(p != pHead) {//绕个圈  已经没有空节点了  
        printf("%d ",p->data );//改数据类型记得的时候%d也要改  
        p = p->pNext ;  
    }
	printf("\n");
    return;  
}
/************************************************************************/
/* 分割线                                                               */
/************************************************************************/
void CreateTail1(pNode pHead,pNode &tailpointer) {
//	tailpointer//尾指针 指向尾节点和头指针指向首节点一个意思
	printf("输入节点个数:");  
    int n,i = 0;  
    scanf("%d",&n);  
    pNode pTail = pHead ; //尾节点
    while( i < n) {  
        datatype item;  
        printf("请输入节点值:");  
        scanf("%d",&item);  
        pNode pNew = (pNode)malloc(sizeof(Node));
        pNew->data = item;  
          //这里和单向链表不一样
        pTail->pNext = pNew;//把pNew给尾节点做后继  
        pNew->pNext = pHead;//pNew指向了头  
        pTail = pNew;//让pNew做尾节点 
		tailpointer->pNext = pTail;//尾指针始终指向尾节点
          
        i++;  
    }  
    return ;  

}
//==============================
/*
	这里合并只是为了演示下尾指针法合并的方便性,
	所以只是单纯的把俩个链表连接起来而已

  分析一下,表都有头结点 尾指针,那么我a的尾节点(不是尾指针哈)连上b的首节点(不是头结点哈),
  然后b的尾节点再指向a的头指针,合并完毕,等会去画个图。
      Ahead-1-2-3-tailpointerA    Bhead-6-7-tailpointerB
	  ^|_________|				  ^|_______|	
	  不够形象,大致酱紫吧。
				|-----------------------|
	  Ahead-1-2-3-tailpointerA    Bhead-6-7-tailpointerB	
	  ^|___________________________________|


*/
pNode Merge1(pNode tailpointerA,pNode tailpointerB) {
	 pNode Atailnode = tailpointerA->pNext;// a的尾节点3
	 pNode Ahead = Atailnode->pNext;//a的头结点
	 pNode Btailnode = tailpointerB->pNext;// b的尾节点7
	 pNode Bhead = Btailnode->pNext;//B的头结点
	
	 Atailnode->pNext = Bhead->pNext;//a的尾节点3指向b的首节点6
	 Btailnode->pNext = Ahead;//b的尾节点指向a的头结点
	 tailpointerA->pNext = Btailnode;//a的尾指针指向b的尾节点7
	
	 return Ahead;//返回a的头结点
}

//=========================================== 
int main() {
	pNode p1;
//	Init(p1);
//	CreateTail(p1);
//	printf("长度是:%d\n ",length(p1));
//	Traverse(p1);
	Init(p1);
	pNode tailpointer1 =(pNode)malloc(sizeof(Node ));//不能这样tailpointer = p;因为p是个双向链表,不信你试试
	tailpointer1->pNext = NULL;//算是吧tailpointer1给初始化的完整了,挺烦的 艹
	CreateTail1(p1,tailpointer1);
	printf("长度是:%d\n ",length(p1));
	Traverse(p1);

	pNode p2;
	Init(p2);
	pNode tailpointer2 = (pNode)malloc(sizeof(Node ));
	tailpointer2->pNext = NULL;
	CreateTail1(p2,tailpointer2);
	printf("长度是:%d\n ",length(p2));
	Traverse(p2);
	printf("\n合并:\n");
	if(tailpointer1->pNext  && tailpointer2->pNext) {//空表没意思
		p1 = Merge1(tailpointer1,tailpointer2);
		Traverse(p1);
	}

	free(p1);
	free(p2);
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值