结构声明:
//类型声明
typedef int dataType;
struct list
{
dataType data; //存放数据
struct list * pNext; //指向下一个结点
};
typedef struct list LIST;
头文件声明:
#ifndef _LINKCIRMAIN_H_
#define _LINKCIRMAIN_H_
//常量定义
enum E_RESULT
{
ERROR = -1,
SUCCESS,
TAIL = -1,
HEAD,
};
//类型声明
typedef int dataType;
struct list
{
dataType data; //存放数据
struct list * pNext; //指向下一个结点
};
typedef struct list LIST;
//全局变量的声明
//函数声明
/*
函数名: createList
函数功能:创建线性表
函数参数:无
函数返回值:成功时,返回指向线性表首地址的指针;失败时,返回NULL。
*/
LIST * createList();
/*
函数名: reverseList
函数功能:逆序一个单向循环链表
函数参数:无
函数返回值:成功时,返回新的指向线性表首地址的指针;失败时,返回NULL。
*/
LIST * reverseList(LIST * pList);
/*
函数名: catListSort
函数功能:连接两个已知尾节点的有序单向循环链表
函数参数:无
函数返回值:成功时,返回新的指向线性表首地址的指针;失败时,返回NULL。
*/
LIST * catListSort(LIST * pTail1,LIST *pTail2);
/*
求循环链表的尾部
*/
LIST * GetTail(LIST * pList);
/*
连接两个已知的尾节点单向循环链表
*/
LIST * catList(LIST * pTail1,LIST *pTail2);
/*
函数名: insertDataToList
函数功能:给线性表指定位置插入数据
函数参数:
LIST * pList : 线性表首地址
int offset : 插入的位置, offset为0表示头插,offset为-1表示尾插。
dataType newData : 准备插入的数据
函数返回值:成功时,返回0;失败时,返回-1。
*/
int insertDataToList ( LIST * pList, int offset, dataType newData );
/*
函数名: showList
函数功能:显示线性表中元素
函数参数:LIST * pList : 线性表首地址
函数返回值:无
*/
void showList ( LIST * pList );
/*
函数名: destroyList
函数功能:销毁线性表
函数参数:LIST * pList : 线性表首地址
函数返回值:无
*/
void destroyList ( LIST * pList );
/*
函数名:deleteDataFromList
函数功能:从线性表删除一个元素
函数参数:
LIST * pList : 线性表首地址
int offset : 删除的位置, offset为0表示头删,offset为-1表示尾删。
dataType * pData : 保存被删除元素
函数返回值:成功时,返回0;失败时,返回-1。
*/
int deleteDataFromList ( LIST * pList, int offset, dataType * pData );
/*
函数名: searchDataFromList
函数功能:从线性表中查找元素
函数参数:
LIST * pList : 线性表首地址
dataType data : 要查找的元素
函数返回值:成功时,返回被查找元素的位置;失败时,返回-1。//约定首结点下标为0
*/
int searchDataFromList ( LIST * pList, dataType data );
/*
函数名: updateData
函数功能:修改线性表中元素的值
函数参数:
LIST * pList : 线性表首地址
dataType oldData : 修改之前的元素
dataType newData : 修改之后的元素
函数返回值:成功时,返回0;失败时,返回-1。
*/
int updateData ( LIST * pList, dataType oldData, dataType newData ); //p = p->pNext
#endif // _LIST_H_
操作实现:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "LinkCirMain.h"
/*
函数名: createList
函数功能:创建线性表
函数参数:无
函数返回值:成功时,返回指向线性表首地址的指针;失败时,返回NULL。
*/
LIST * createList()
{
LIST * pList = NULL;
pList = ( LIST * ) malloc ( sizeof( LIST ) );
if (NULL != pList)
{
memset ( pList, 0, sizeof ( LIST ) );
pList->pNext = NULL;
}
return pList;
}
/*
函数名: catListSort
函数功能:连接两个已知尾节点的有序从大到小单向循环链表
函数参数:无
函数返回值:成功时,返回新的指向线性表首地址的指针;失败时,返回NULL。
*/
LIST * catListSort(LIST * pTail1,LIST *pTail2)
{
LIST *pTmp=NULL;
LIST *pRtn=NULL;
LIST *pDel=NULL;
LIST *p1=NULL;
LIST *p2=NULL;
LIST *pt=NULL;
if ( NULL == pTail1
&& NULL == pTail2)
{
return NULL;
}else if(NULL == pTail1)//第一个为空返回第二个
{
pRtn = pTail2->pNext;
return pRtn;
}else if(NULL == pTail2)//第二个为空返回第一个
{
pRtn = pTail1->pNext;
return pRtn;
}else if(pTail1->pNext->pNext->data <= pTail2->data)
{//第一个的第一个元素(最大值)小于第二个的最小值那么直接追加
printf("%d %d\n",pTail1->pNext->pNext->data,pTail2->data);
pDel = pTail1->pNext;
pTail1->pNext = pTail2->pNext;
pTail2->pNext = pDel->pNext;
free(pDel);
pDel=NULL;
return pTail1->pNext;
}else if(pTail2->pNext->pNext->data <= pTail1->data)
{//第二个的第一个元素(最大值)小于第一个的最小值那么直接追加
pDel = pTail2->pNext;
pTail2->pNext = pTail1->pNext;
pTail1->pNext=pDel->pNext;
free(pDel);
pDel=NULL;
return pTail2->pNext;
}else
{ //如果上述条件都不符合则 //pList1 = 99, 88, 44, 33, 31 //pList2 = 77, 55, 45, 44
//先保护首节点,也就是强制返回第一的首地址,将新的列表链到第一个链表的首地址之后
pRtn=pTail1->pNext;
//获取第一链表的第一个元素的地址
p1 = pTail1->pNext->pNext;
//获取第二链表的第一个元素的地址
p2 = pTail2->pNext->pNext;
//做一个指针标记点,用来标记新的链表的最后一个元素地址
pt = pRtn;
//获取将被要删除的第二个链表头节点
pDel = pTail2->pNext;
while(1)
{
if(p1->data >= p2->data)
{
pt->pNext = p1;//如果第一个链表的某个元素大于第二个,那么将这个元素链到新链表中
pt = p1;//移动做一个指针标记点,指向新链表最后的元素地址
if(p1->pNext == pRtn)//如果等于首节点,那么是最后一个元素,则将另一个直接追加
{
p1->pNext = p2;
pTail2->pNext = pRtn;//让另一个的尾节点指向首节点,完成循环链表
free(pDel);
pDel=NULL;
return pRtn;
}
p1 = p1->pNext; //向后移动指针
}
if(p2->data > p1->data)
{
pt->pNext = p2;//如果第一个链表的某个元素大于第二个,那么将这个元素链到新链表中
pt = p2;//移动做一个指针标记点,指向新链表最后的元素地址
if(p2->pNext == pTail2->pNext)//如果等于首节点,那么是最后一个元素,则将另一个直接追加
{
p2->pNext = p1;
pTail1->pNext = pRtn;//让另一个的尾节点指向首节点,完成循环链表
free(pDel);
pDel=NULL;
return pRtn;
}
p2 = p2->pNext;//向后移动指针
}
}
}
}
/*
函数名: reverseList
函数功能:逆序一个单向循环链表
函数参数:线性表首地址的指针
函数返回值:成功时,返回新的指向线性表首地址的指针;失败时,返回NULL。
*/
LIST * reverseList(LIST * pList)
{
LIST *pRtn = NULL,*pFront = NULL,*qTmp=NULL;
if ( NULL == pList)
{
return NULL;
}
pRtn=pList;//保存头节点
pFront = pList->pNext;//保存第一个地址
pList->pNext = pList; //原有头指向 pList头节点
while(pFront!=pList)
{
qTmp = pFront->pNext; //获取p之后的节点地址
//将第一个节点的指针域置空,当程序第一次进如循环,则第一个节点将会是最后
pFront->pNext = pList->pNext;
pList->pNext = pFront; //将第一个节点(当前的节点链接到头节点),利用头插法实现逆置
pFront=qTmp; //更新 ,将第二个节点(当前节点的后一个节点) 赋值给p
}
return pRtn;
}
/*
函数名: catList
函数功能:连接两个已知尾节点的单向循环链表
函数参数:无
函数返回值:成功时,返回新的指向线性表首地址的指针;失败时,返回NULL。
*/
LIST * catList(LIST * pTail1,LIST *pTail2)
{
LIST *pTmp=NULL;
LIST *pRtn=NULL;
LIST *pDel=NULL;
if ( NULL == pTail1
&& NULL == pTail2)
{
return NULL;
}else if(NULL == pTail1)
{
pRtn = pTail2->pNext;
return pRtn;
}else if(NULL == pTail2)
{
pRtn = pTail1->pNext;
return pRtn;
}else
{
pDel = pTail1->pNext;
pTail1->pNext = pTail2->pNext;
pTail2->pNext=pDel->pNext;
free(pDel);
pDel=NULL;
}
return pTail1->pNext;
}
/*
函数名: GetTail
函数功能:获取一个单向循环链表的尾巴
函数参数:无
函数返回值:成功时,返回尾巴;失败时,返回NULL。
*/
LIST * GetTail(LIST * pList)
{
LIST * pTail = NULL;
LIST *pTmp=NULL;
if ( NULL == pList)
{
return NULL;
}
pTmp = pList->pNext;
while(pList != pTmp->pNext)
{
pTmp=pTmp->pNext;
//pTmp->pNext = pTmp->pNext;
}
//pTmp->pNext = pNew;
//让最后的尾节点的指针域指向头节点
//pNew->pNext = pList;
return pTmp;
}
/*
函数名: insertDataToList
函数功能:给线性表指定位置插入数据
函数参数:
LIST * pList : 线性表首地址
int offset : 插入的位置, offset为0表示头插,offset为-1表示尾插。
dataType newData : 准备插入的数据
函数返回值:成功时,返回0;失败时,返回-1。
*/
int insertDataToList ( LIST * pList, int offset, dataType newData )
{
LIST * pNew = NULL;
LIST *pTmp=NULL;
int index=1;
if ( NULL == pList
|| offset < TAIL )
{
return ERROR;
}
//新建结点
pNew = ( LIST * ) malloc ( sizeof ( LIST ) );
if ( NULL == pNew )
{
return ERROR;
}
memset ( pNew, 0, sizeof ( LIST ) );
pNew->data = newData ;
pNew->pNext = NULL;
if ( HEAD == offset )//头插法
{
if(NULL == pList->pNext)
{
pList->pNext = pNew;
pNew->pNext = pList;
}else
{
//保护头结点之后的所有结点
pNew->pNext = pList->pNext;
//连接新结点到头结点后面
pList->pNext = pNew;
}
return 0;
}
else if ( TAIL == offset )//尾插法
{
pTmp = pList->pNext;
while(pList != pTmp->pNext)
{
pTmp=pTmp->pNext;
//pTmp->pNext = pTmp->pNext;
}
pTmp->pNext = pNew;
//让最后的尾节点的指针域指向头节点
pNew->pNext = pList;
printf("今天的作业\r\n");
return SUCCESS;
}
else
{
pTmp=pList->pNext;
while(pList != pTmp->pNext)
{
if(index == offset)
{
break;
}
index++;
pTmp=pTmp->pNext;
pTmp->pNext = pTmp->pNext;
}
if(pTmp != NULL && NULL != pTmp->pNext)
{
pNew->pNext=pTmp->pNext;
pTmp->pNext = pNew;
printf("插入到中间%d的某个位置,今天的选做作业\r\n",index);
return 0;
}else
{
printf("您输入的位置已经超出链表长度\n");
free(pNew);
pNew=NULL;
return -1;
}
}
return SUCCESS;
}
/*
函数名: searchDataFromList
函数功能:从线性表中查找元素
函数参数:
LIST * pList : 线性表首地址
dataType data : 要查找的元素
函数返回值:成功时,返回被查找元素的位置;失败时,返回-1。//约定首结点下标为0
*/
int searchDataFromList ( LIST * pList, dataType data )
{
int index=0;
LIST *p=NULL;
if(pList == NULL)
{
return -1;
}
p=pList->pNext;
while(NULL != p)
{
if(p->data == data)
{
return index;
}
index++;
p = p->pNext;
}
return -1;
}
/*
函数名: showList
函数功能:显示线性表中元素
函数参数:LIST * pList : 线性表首地址
函数返回值:无
*/
void showList ( LIST * pList )
{
LIST * p = NULL;
if ( NULL == pList
|| NULL == pList->pNext )
{
return ;
}
p = pList->pNext;
while ( pList != p)
{
printf("%d --> ", p->data);
p = p->pNext;
}
printf("^\r\n");
return ;
}
/*
函数名: destroyList
函数功能:销毁线性表
函数参数:LIST * pList : 线性表首地址
函数返回值:无
*/
void destroyList ( LIST * pList )
{
LIST * pDel = NULL;
if ( NULL == pList )
return ;
while ( pList != pList->pNext )
{
//让pDel指向首结点
pDel = pList->pNext;
//保护pDel后的所有结点
pList->pNext = pDel->pNext;
//释放pDel
free( pDel );
pDel = NULL;
}
free( pList );
pList = NULL;
return ;
}
/*
函数名:deleteDataFromList
函数功能:从线性表删除一个元素
函数参数:
LIST * pList : 线性表首地址
int offset : 删除的位置, offset为0表示头删,offset为-1表示尾删。
dataType * pData : 保存被删除元素
函数返回值:成功时,返回0;失败时,返回-1。
*/
int deleteDataFromList ( LIST * pList, int offset, dataType * pData )
{
LIST * pDel = NULL;
LIST *pTmp=NULL;
int index=0;
if ( NULL == pList
|| NULL == pList->pNext
|| offset < TAIL )
{
return ERROR;
}
if ( HEAD == offset )//删除首结点
{
//让pDel指向首结点
pDel = pList->pNext;
//保护pDel后的所有结点
pList->pNext = pDel->pNext;
//保存被删除元素
if ( NULL != pData )
{
* pData = pDel->data;
}
//释放pDel
free( pDel );
pDel = NULL;
return 0;
}
else if ( TAIL == offset )
{
pDel=pList->pNext;
//删除尾结点 今天的作业\r\n
while(NULL != pDel->pNext)
{
pTmp=pDel;
pDel = pTmp->pNext;
pDel->pNext = pDel->pNext;
}
pTmp->pNext=NULL;
if ( NULL != pData )
{
* pData = pDel->data;
}
free(pDel);
pDel=NULL;
return 0;
}
else
{
//今天的作业\r\n
pDel=pList->pNext;
while(NULL != pDel->pNext)
{
if(index == offset)
{
break;
}
index++;
pTmp = pDel;
pDel=pTmp->pNext;
pDel->pNext = pDel->pNext;
}
if(pDel != NULL&& NULL != pDel->pNext)
{
if ( NULL != pData )
{
* pData = pDel->data;
}
pTmp->pNext=pDel->pNext;
free(pDel);
pDel=NULL;
return 0;
}else
{
printf("您输入的位置已经超出链表长度\n");
return -1;
}
}
return SUCCESS;
}
测试代码:
#include <stdio.h>
#include "LinkCirMain.h"
//函数的使用
int main()
{
LIST * pList1 = NULL,*pList2 = NULL;
LIST * pTail1 = NULL,*pTail2=NULL;
LIST * pList3 = NULL;
LIST * pList6 = NULL;
LIST * pList7 = NULL;
dataType data;
int index=0;
//创建链表
pList1 = createList();
if ( NULL == pList1 )
{
printf("create list1 error\r\n");
return -1;
}
pList2 = createList();
if ( NULL == pList2 )
{
printf("create list2 error\r\n");
return -1;
}
//存放年龄 pList1
insertDataToList ( pList1, 0, 31 );//插入位置起始为0
insertDataToList ( pList1, 0, 33 );
insertDataToList ( pList1, 0, 44 );
insertDataToList ( pList1, 0, 88 );
insertDataToList ( pList1, 0, 99 ); //1,2,3,4,5
//insertDataToList ( pList1, -1, 6 ); //尾插法
//存放年龄 pList1
//insertDataToList ( pList2, 0, 29 );//插入位置起始为0
insertDataToList ( pList2, 0, 44 );
insertDataToList ( pList2, 0, 45 );
insertDataToList ( pList2, 0, 55 );
insertDataToList ( pList2, 0, 77 );//11,22,33,44,55
//insertDataToList ( pList2, -1, 66 ); //尾插法
printf("pList1\n");
showList ( pList1 );
printf("pList2\n");
showList ( pList2 );
//printf("测试反转pList7\n");
//pList7 = reverseList(pList1);
//showList ( pList7 );
//return 0;
pTail1 = GetTail(pList1);
pTail2 = GetTail(pList2);
printf("pList1 - %d\n",pTail1->data);
printf("pList2 - %d\n",pTail2->data);
//一个最小值大于另一个的最大值,做链接
//pList1 = 1,2,3,4,5
//pList1 = 11,22,33,44,55
//pList6 = catListSort(pTail1,pTail2);
//pList6 = catListSort(pTail2,pTail1);
//长度相等
//pList1 = 99, 88, 44, 33, 31
//pList2 = 77, 55, 45, 44, 29
//pList6 = catListSort(pTail1,pTail2);
//pList6 = catListSort(pTail2,pTail1);
//长度不相等
//pList1 = 99, 88, 44, 33, 31
//pList2 = 77, 55, 45, 44
//pList6 = catListSort(pTail1,pTail2);
pList6 = catListSort(pTail2,pTail1);
printf("pList6\n");
showList ( pList6 );
//链接两个单向循环链表
/*
printf("pList4\n");
pList4 = catList(NULL,pTail2);
showList ( pList4 );
printf("pList5\n");
pList5 = catList(pTail1,NULL);
showList ( pList5 );
pList3 = catList(pTail1,pTail2);
printf("pList3\n");
showList ( pList3 );
insertDataToList ( pList2, 2, 77 ); //尾插法
showList ( pList3 );
*/
//销毁顺序表
destroyList ( pList3 );
destroyList ( pList6 );
pList1 = NULL;
pList2 = NULL;
pList3 = NULL;
pList6 = NULL;
return 0;
}