创建链表有头插法和尾插法两种方法,今天要说的是尾插法,尾插法逻辑比较简单,直接上图
只要将新节点新节点的数据域放上要存放的数据,然后将新节点的指针域置空让其当作尾节点,然后让指向尾节点的pTail的指针域指向新节点,然后赋值给指向尾节点的pTail即可。
PNODE Create_list()
{
PNODE pHead = (PNODE)malloc(sizeof(NODE));//创建带有头指针的链表
if (NULL == pHead)//判断内存分配是否成功
{
printf("内存分配失败,程序终止\n");
exit(-1);
}
PNODE pTail = pHead;
pTail->pNext = NULL;//创建指向尾节点的指针
int flag = 1;//程序结束标志为1继续循环,为0结束循环
char str;//接受用户输入的数据
printf("请输入想要存放的数据,以$为结束标志:");
while (flag)
{
str = getchar();
if (str != '$')
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));//创建新节点
if (NULL == pNew)//判断内存分配是否成功
{
printf("内存分配失败,程序终止!\n");
exit(-1);
}
pNew->data = str;//将数据存放在新节点的数据域
pTail->pNext = pNew;//将原来最后一个节点的指针域指向新节点
pNew->pNext = NULL;//将新节点的指针域置空
pTail = pNew;//将新节点作为最后一个节点,并赋值给pTail,依次循环
}
else
flag = 0;
}
return pHead;
}
在主函数中调用,查看链表是否创建成功
int main(void)
{
PNODE pList;
pList = Create_list();
Treaverse_list(pList);//遍历链表
return 0;
}
结果为
链表创建成功!
说完创建链表以后,单链表还有许多其他操作,接下来会依次介绍链表的各种基本操作:
- 链表的初始化
PNODE Init_list() { PNODE pHead = (PNODE)malloc(sizeof(NODE));//创建一个带有头节点的链表 if (NULL == pHead) { printf("内存分配失败,程序终止\n"); exit(-1); } pHead->pNext = NULL;//将首节点的指针域置空 return pHead; }
- 销毁链表
void DestroyList(PNODE pHead) { PNODE q; while (pHead != NULL)//直到头节点也为空说明链表被销毁 { q = pHead;//q指向要被销毁的节点 pHead = pHead->pNext;//将头指针指向被销毁节点的下一个节点 free(q);//销毁节点 } }
- 清空链表(和销毁链表很类似,但是清空链表会保留头节点)
void Clear_list(PNODE pHead) { PNODE cl = pHead->pNext;//指向头节点的下一个节点,即将要清除的节点 PNODE q = cl;//用来标记链表,来依次释放节点,防止内存泄露 while (cl != NULL)//cl不为空说明链表没有清空完,为空则说明链表已经清空 { q = cl->pNext;//将q指向要清空的下一个节点 free(cl);//清除节点 cl = q;//cl也指向的下一个节点 } pHead->pNext = NULL;//首节点指针域置空,说明链表为空 }
- 判断链表是否为空
bool Is_empty(PNODE pHead) { if (NULL == pHead->pNext)//如果首节点的指针域为空,说明链表为空,反之则不为空 { printf("链表为空\n"); return true; } else { printf("链表不为空\n"); return false; } }
-
判断某元素是否在链表中
bool Compare(PNODE pHead, char str) { PNODE p = pHead->pNext;//将p指向存放元素的首节点 while (NULL != p) { if (str == p->data)//依次判断所要寻找的元素在不在链表的节点中 { return true;//存在就直接返回true终止循环 } else p = p->pNext; } return false;//循环结束都没有的话说明不存在 }
- 获取某个元素的直接后继元素
char NextElem(PNODE pHead, char str) { if (Compare(pHead, str)) { int i = 0; int count = 0; char result; PNODE p = pHead->pNext; PNODE q = p; while (NULL != p) { if (str == p->data) break; else { count++; p = p->pNext; } } count++;//获得直接后继的索引值 while (q != NULL && i <= count)//取所需元素的直接后继元素 { q = q->pNext; i++; } if (NULL == q) { printf("取值失败!\n"); exit(-1); } result = q->data; return result; } else return 0; }
- 获取某个元素的直接前驱元素
char PriorElem(PNODE pHead, char str ) { if (Compare(pHead, str)) { int i=0; int count = 0; char result; PNODE p = pHead->pNext; PNODE q = p; while (NULL != p) { if (str == p->data) break; else { count++; p = p->pNext; } }//获得直接前驱的索引值 while (q != NULL && i <= count)//取所需元素的直接前驱元素 { q = q->pNext; i++; } if (NULL == q) { printf("取值失败!\n"); exit(-1); } result = q->data; return result; } else return 0; }
- 获取链表的长度
int Len_list(PNODE pHead) { int len = 0; PNODE p = pHead;//将p指向首节点 while (NULL != p)//依次移动p如果不为空就让长度加一,为空说明链表结束 { len++; p = p->pNext; } return len; }
- 遍历链表
void Treaverse_list(PNODE pHead) { PNODE p = pHead->pNext;//新定义一个节点存放链表中的第一个节点 while (NULL != p)//如果p不是空的就打印数据域中的数据,否则说明遍历完链表了 { printf("%c", p->data); p = p->pNext;//通过指针域来让节点P移动 依次遍历链表 } printf("\n"); return;//表示函数结束 }
下篇将详细讲解向某个位置插入和删除某个位置节点的操作