废话少说,先上代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node* pNext;
}NODE,*PNODE;
PNODE create_list(void); //初始化链表
void traverse_list(PNODE pHead); //为链表添加元素
bool is_empty(PNODE pHead); //判断是否为空链表
int length_list(PNODE pHead); //求链表的长度
void sort_list(PNODE pHead); //排序
bool insert_list(PNODE pHead, int pos, int val); //插入
bool delete_list(PNODE pHead, int val); //删除
int main(void)
{
int length;
PNODE pHead = NULL;
pHead = create_list();
traverse_list(pHead);
if (is_empty(pHead))
{
printf("链表是空链表!\n");
}
else
{
printf("链表不是空链表!\n");
}
length = length_list(pHead);
printf("排序后链表为:\n");
sort_list(pHead);
traverse_list(pHead);
insert_list(pHead, 3, 3);
printf("在链表第三个元素前插入3之后得到的链表为:\n");
traverse_list(pHead);
delete_list(pHead, 3);
printf("删除链表中数字域存储为3的值得到的链表为:\n");
traverse_list(pHead);
return 0;
}
PNODE create_list(void)
{
int length;
int i;
int value;
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if (pHead == NULL)
{
printf("内存分配失败!");
exit(1);
}
PNODE pTail = pHead;
pTail->pNext = NULL;
printf("请输入链表的有效长度:\n");
scanf_s("%d", &length);
for (i = 0; i < length; i++)
{
printf("请输入第%d个元素的值:\n", i + 1);
scanf_s("%d", &value);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (pNew == NULL)
{
printf("内存分配失败!");
exit(1);
}
pNew->data = value;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
void traverse_list(PNODE pHead)
{
PNODE p = pHead->pNext;
while (p != NULL)
{
printf("%d ", p->data);
p = p->pNext;
}
putchar('\n');
}
bool is_empty(PNODE pHead)
{
if (pHead->pNext == NULL)
{
return true;
}
else
{
return false;
}
}
int length_list(PNODE pHead)
{
int i = 0;
PNODE p = pHead;
while (p->pNext != NULL)
{
i++;
p = p->pNext;
}
return i;
}
void sort_list(PNODE pHead)
{
int i, j, temp;
int length = length_list(pHead);
PNODE p, q;
for(i = 0,p = pHead->pNext; i < length; i++,p = p->pNext)
{
for(j = i + 1, q = p->pNext; j < length;j++, q = q->pNext)
{
if (p->data > q->data)
{
temp = p->data;
p->data = q->data;
q->data = temp;
}
}
}
}
bool insert_list(PNODE pHead, int pos, int val)
{
int i = 0;
PNODE p = pHead;
while (p != NULL && i < pos - 1)
{
p = p->pNext;
i++;
}
if (i > pos - 1 || p == NULL)
{
printf("插入失败!\n");
return false;
}
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (pNew == NULL)
{
printf("动态内存分配失败!\n");
exit(1);
}
pNew->data = val;
pNew->pNext = p->pNext;
p->pNext = pNew;
return true;
}
bool delete_list(PNODE pHead, int val)
{
int i = 0;
int length;
PNODE p = pHead;
PNODE q = (PNODE)malloc(sizeof(NODE));
if (q == NULL)
{
printf("内存分配失败!\n");
exit(1);
}
q = p->pNext;
length = length_list(pHead); //链表被删除一个元素后长度会减小
while (i < length) //while(i<length_list(pHead))中length_list(pHead)减少一个就会相应减少,导致最后几个元素无法被选中
{
if (q->data == val)
{
PNODE del = q;
q = q->pNext;
p->pNext = p->pNext->pNext;
free(del);
}
else
{
p = q;
q = p->pNext;
}
i++;
}
return true;
}
注:写完编译器还是一直给我报一个问题,使用未初始化的内存“*q”。求大佬解答!!!
无论是初始化链表还是改动链表,都是对链表的数据域和指针域进行改动。
1、初始化链表
首先要给头指针分配动态内存,头指针指向的就是第一个元素,新增加元素的指针设为pNew,那么当链表长度为0时可以直接添加pNew,而链表有长度时,通过头指针无限指向pNext(指针域)来添加就使程序变得难以理解,不如增加一个结点,把该结点(尾结点)的指针pTail指向新增结点,从而达到链表结点的增加。
PNODE create_list(void)
{
int length;
int i;
int value;
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if (pHead == NULL)
{
printf("内存分配失败!");
exit(1);
}
PNODE pTail = pHead;
pTail->pNext = NULL;
printf("请输入链表的有效长度:\n");
scanf_s("%d", &length);
for (i = 0; i < length; i++)
{
printf("请输入第%d个元素的值:\n", i + 1);
scanf_s("%d", &value);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (pNew == NULL)
{
printf("内存分配失败!");
exit(1);
}
pNew->data = value;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return pHead;
}
返回头结点就能得到整个链表的所有结点。
2、排序(从小到大)
利用两个循环进行比较,如果左边的值小于右边则进行互换。
void sort_list(PNODE pHead)
{
int i, j, temp;
int length = length_list(pHead);
PNODE p, q;
for(i = 0,p = pHead->pNext; i < length; i++,p = p->pNext)
{
for(j = i + 1, q = p->pNext; j < length; j++, q = q->pNext)
{
if (p->data > q->data)
{
temp = p->data;
p->data = q->data;
q->data = temp;
}
}
}
}
3、插入
在第pos个结点上插入一个值(数据域)为val的结点
bool insert_list(PNODE pHead, int pos, int val)
{
int i = 0;
PNODE p = pHead;
while (p != NULL && i < pos - 1)
{
p = p->pNext;
i++;
}
if (i > pos - 1 || p == NULL)
{
printf("插入失败!\n");
return false;
}
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (pNew == NULL)
{
printf("动态内存分配失败!\n");
exit(1);
}
pNew->data = val;
pNew->pNext = p->pNext;
p->pNext = pNew;
return true;
}
注意的是特殊情况,如果pos小于1或者大于链表长度+1那么无法插入。
pos结点前p的指针域指向pNew,pNew的指针域指向原来p指向的结点。
4、删除
删除每个值为val的结点删除后前结点直接指向被删除结点的后结点,并把被删除结点内存释放掉。
bool delete_list(PNODE pHead, int val)
{
int i = 0;
int length;
PNODE p = pHead;
PNODE q = (PNODE)malloc(sizeof(NODE));
if (q == NULL)
{
printf("内存分配失败!\n");
exit(1);
}
q = pHead->pNext;
length = length_list(pHead); //链表被删除一个元素后长度会减小
while (i < length) //while(i<length_list(pHead))中length_list(pHead)减少一个就会相应减少,导致最后几个元素无法被选中
{
if (q->data == val)
{
PNODE del = q;
q = q->pNext;
p->pNext = p->pNext->pNext;
free(del);
}
else
{
p = q;
q = p->pNext;
}
i++;
}
return true;
}
注:写这个算法的时候偷懒直接写while(i <length_list(pHead)),这样写当删除一个元素时长度减少,循环次数减少导致无法对后面的结点进行判断!!!应当把长度length直接求出来,进行length次循环才能找到全部的值为val的结点。