#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Node {
int data;
struct Node *pNext;
}NODE, *PNODE;
PNODE create_list();
void traverse_list(PNODE);
bool is_empty_list(PNODE);
int len_list(PNODE);
void sort_list(PNODE);
bool insert_list(PNODE, int, int);
bool delete_list(PNODE, int, int *);
bool getElem(PNODE, int, int *);
bool clear_list_recommended(PNODE *);
bool clear_list(PNODE *);
bool clear_list_error_usage(PNODE);
bool clear_list_recommended(PNODE *ppHead) {
PNODE q, p = (*ppHead)->pNext;
while (p) {
q = p->pNext;
free(p);
p = q;
}
(*ppHead)->pNext = NULL;
return true;
}
/* 此用法头结点的类型与其它节点相同
* 缺点为清空后头节点的为最后一个节点(数据还在),pNext指向NULL
*/
bool clear_list(PNODE *ppHead) {
PNODE q;
while ((*ppHead)->pNext) {
q = (*ppHead)->pNext;
*ppHead = (*ppHead)->pNext->pNext;
free(q);
}
return true;
}
/* 错误用法
* 形参不是PNODE *,并未影响函数外部的指针变量
* 会导致原头指针指向的头节点还是指向原来的第1个元素(但已经变为垃圾值)
*/
bool clear_list_error_usage(PNODE pHead) {
PNODE q;
while (pHead->pNext) {
q = pHead->pNext;
pHead = pHead->pNext->pNext;
free(q);
}
return true;
}
bool getElem(PNODE pHead, int i, int *pVal)
{
PNODE p = pHead->pNext;
int j = 1;
while (p != NULL && j < i) {
p = p->pNext;
++j;
}
if (p != NULL && j == i) {
*pVal = p->data;
return true;
}
return false;
}
bool delete_list(PNODE pHead, int pos, int * pVal)
{
int i = 0;
PNODE p = pHead;
// i等于几就代码i指向第几个节点,我们要让p指向pos前面1个节点
while (NULL != p && i < pos-1) {
p = p->pNext;
i++;
}
// 如果下面这行用if (i != pos-1 || p->pNext == NULL) { 则上面也需要改为 while (NULL != p->pNext && i < pos-1) {
if (i != pos-1 || p == NULL) {
return false;
}
PNODE q = p->pNext;
*pVal = q->data;
//p->pNext = p->pNext->pNext;
p->pNext = q->pNext;
free(q);
q = NULL; //函数中的局部变量,个人感觉不需要置空,这里应该是为了保持习惯
return true;
}
bool insert_list(PNODE pHead, int pos, int val)
{
int i = 0;
PNODE p = pHead;
// i等于几就代码i指向第几个节点,我们要让p指向pos前面1个节点
while (NULL != p && i < pos-1) {
p = p->pNext;
i++;
}
//if (i > pos-1 || p == NULL)
if (i != pos-1 || p == NULL)
return false;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if ( NULL == pNew ) {
printf("内存分配失败");
return false;
}
pNew->data = val;
pNew->pNext = p->pNext;
p->pNext = pNew;
printf("pNew->data = %d\n", pNew->data);
return true;
}
void sort_list(PNODE pHead)
{
PNODE p, q;
int t;
for (p = pHead->pNext; p != NULL; p=p->pNext) {
for (q = p->pNext; q !=NULL; q=q->pNext) {
if (p->data > q->data) {
t = p->data;
p->data = q->data;
q->data = t;
}
}
}
}
int len_list(PNODE pHead)
{
int len = 0;
PNODE p = pHead->pNext;
while (NULL != p) {
len++;
p = p->pNext;
}
return len;
}
bool is_empty_list(PNODE pHead)
{
if (pHead->pNext == NULL)
return true;
return false;
}
void traverse_list(PNODE pHead)
{
PNODE p = pHead->pNext;
while (p != NULL) {
printf("%d ", p->data);
p = p->pNext;
}
putchar('\n');
}
PNODE create_list()
{
int len;
int val;
// 头指针指向头节点
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if (NULL == pHead) {
printf("内存分配失败\n");
exit(-1);
}
// 使用一个尾指针始终指向结尾
PNODE pTail = pHead;
pTail->pNext = NULL;
printf("请输入链表长度:");
scanf("%d", &len);
for (int i=0; i<len; i++) {
printf("请输入链表的值:");
scanf("%d", &val);
// p为临时节点
PNODE p = (PNODE)malloc(sizeof(NODE));
if (NULL == p) {
printf("内存分配失败\n");
exit(-1);
}
p->data = val;
p->pNext = NULL;
// 尾节点的下一个指向刚创建的临时节点
pTail->pNext = p;
// 更新尾指针
pTail = p;
}
return pHead;
}
int main(void)
{
PNODE pHead = NULL;
pHead = create_list();
traverse_list(pHead);
if (is_empty_list(pHead)) {
printf("链表为空\n");
}
else {
printf("链表不空\n");
}
int len = len_list(pHead);
printf("链表长度为:%d\n", len);
sort_list(pHead);
printf("排序后:\n");
traverse_list(pHead);
printf("插入结果(成功1,失败0):%d\n", insert_list(pHead, 2, 111));
printf("插入后:\n");
traverse_list(pHead);
int val;
if (delete_list(pHead, 1, &val)) {
printf("删除成功:%d\n", val);
}
else {
printf("删除失败\n");
}
traverse_list(pHead);
printf("清空前,头节点的值:%d\n", pHead->data);
printf("清空前, pHead addr is %p, pHead->pNext addr is %p\n", pHead, pHead->pNext);
//clear_list(&pHead);
clear_list_recommended(&pHead);
//clear_list_error_usage(pHead);
printf("清空后,头节点的值:%d\n", pHead->data);
printf("清空后, pHead addr is %p, pHead->pNext addr is %p\n", pHead, pHead->pNext);
//pHead = create_list();
printf("清空后遍历:\n");
traverse_list(pHead);
return 0;
}
output:
[root@8be225462e66 c]# gcc linklist_1.c && ./a.out
请输入链表长度:4
请输入链表的值:11
请输入链表的值:-2
请输入链表的值:3
请输入链表的值:4
11 -2 3 4
链表不空
链表长度为:4
排序后:
-2 3 4 11
pNew->data = 111
插入结果(成功1,失败0):1
插入后:
-2 111 3 4 11
删除成功:-2
111 3 4 11
清空前,头节点的值:0
清空前, pHead addr is 0x67c2a0, pHead->pNext addr is 0x67cb60
清空后,头节点的值:0
清空后, pHead addr is 0x67c2a0, pHead->pNext addr is (nil)
清空后遍历:
[root@8be225462e66 c]#