一、非循环单链表插入节点伪算法
如上图所示,已知有一链表,要想在p所指向的节点的后面插入一个新的节点q,则有两种方法:
伪算法一:
t = p->pNext;
p->pNext = q;
q->pNext = t;
伪算法二:
q->pNext = p->pNext;
p->pNext = q;
二、非循环单链表删除节点伪算法
如上图所示,已知有一链表,要想把p所指向的节点的后面的节点删除,则有伪算法:
t = p->pNext; //使t指向p节点后面将删除的节点,以便后面释放
p->pNext = p->pNext->pNext;
free(t); //free(t)是为了防止内存泄露
三、用C语言实现
/*
2016年9月13日10:28:14
链表复习,创建链表和遍历链表
*/
#include<stdio.h>
#include<malloc.h> //malloc 函数在此头文件
#include<stdlib.h> //exit 函数在此头文件
typedef struct Node
{
int data; //数据域
struct Node * pNext; //指针域
} * PNODE, NODE;
//函数声明
PNODE creat_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 pos, int *pVal);
int main(void) //主函数主要来测试各个函数正确性
{
int val;
PNODE pHead = NULL;
pHead = creat_list(); //创建链表
traverse_list(pHead);
//delete_list(pHead, 2, &val);
insert_list(pHead, 1, 99);
printf("插入后:\n");
traverse_list(pHead);
// sort_list(pHead);
// printf("排序后:\n");
// traverse_list(pHead);
//printf("链表的个数为:%d\n", length_list(pHead));
// if(is_empty(pHead))
// printf("链表为空!\n");
// else
// printf("链表不为空\n");
return 0;
}
PNODE creat_list(void) //创建链表
{
int len; //用来存放节点的个数
int val; //用来临时存放数据域的值
int i;
PNODE pHead = NULL; //头指针
pHead = (PNODE)malloc(sizeof(NODE)); //创建头结点,并使头指针指向头结点
if(NULL == pHead)
{
printf("内存分配失败,程序终止!\n");
exit(-1);
}
PNODE pTail = NULL; //尾指针
pTail = pHead;
pTail->pNext = NULL; //注意此语句不能省
printf("请输入要创建节点的个数:\n");
printf("len = :");
scanf("%d", &len);
printf("\n");
for(i = 0; i < len; ++i)
{
PNODE pNew = NULL;
pNew = (PNODE)malloc(sizeof(NODE)); //创建一个新节点
if(NULL == pNew)
{
printf("内存分配失败,程序终止!\n");
exit(-1);
}
printf("请输入第%d个节点的是:", i+1);
scanf("%d", &val);
printf("\n");
pNew->data = val; //将输入的值赋给新节点的数值域
pTail->pNext = pNew; //使原来的链表的尾指针指向新节点
pNew->pNext = NULL; //注意此语句不能省
pTail = pNew; //更新尾指针
}
return pHead; //返回头指针
}
void traverse_list(PNODE pHead) //遍历链表并输出数据域的值
{
PNODE p = pHead->pNext;
while(NULL != p)
{
printf("%d\n", p->data);
p = p->pNext;
}
return;
}
bool is_empty(PNODE pHead) //判断链表是否为空
{
if(NULL == pHead->pNext)
return true;
else
return false;
}
int length_list(PNODE pHead) //返回链表的长度
{
int len = 0;
PNODE p = pHead->pNext;
while(NULL != p)
{
++len;
p = p->pNext;
}
return len;
}
void sort_list(PNODE pHead) //冒泡排序
{
int i, j, t;
int len = length_list(pHead);
PNODE p, q; //因为链表没有下标,所以用定义了p和q方便链表交换
for(i = 0; i < len-1; ++i) //方法一
{
for(j = 0, p = pHead->pNext; j < len-1-i; ++j, p = p->pNext)
{
q = p->pNext;
if(p->data > q->data) //从小到大排序
{
t = p->data; //只需要交换数据域的内容
p->data = q->data;
q->data = t;
}
}
}
// for(i = 0, p = pHead->pNext; i < len-1; ++i, p = p->pNext) //方法二
// {
// for(j = i+1, q = p->pNext; j < len; ++j, q = q->pNext)
// {
// if(p->data > q->data) //从小到大排序
// {
// t = p->data; //只需要交换数据域的内容
// p->data = q->data;
// q->data = t;
// }
// }
// }
return;
}
//我自己写的
bool insert_list(PNODE pHead, int pos, int val) //在pos位置上插入一个数据域为val的新节点,pos从1开始
{
int i;
PNODE p, t;
if(pos < 0 || pos > length_list(pHead)) //先判断pos的位置是否有效
{
return false;
}
else
{
PNODE pNew = (PNODE)malloc(sizeof(NODE)); //创建一个新节点
if(NULL == pNew)
{
printf("内存分配失败,程序终止!\n");
exit(-1);
}
pNew->data = val;
p = pHead;
for(i = 0; i < pos-1; ++i) //使p指向要删除节点的前一个节点
{
p = p->pNext;
}
t = p->pNext;
p->pNext = pNew;
pNew->pNext = t;
return true;
}
}
/*
//参考郝斌老师写的
bool insert_list(PNODE pHead, int pos, int val)
{
int i = 0;
PNODE p = pHead;
while (NULL!=p && i<pos-1)
{
p = p->pNext;
++i;
}
if (i>pos-1 || NULL==p)
return false;
//如果程序能执行到这一行说明p已经指向了第pos-1个结点,但第pos-1个节点是否存在无所谓
//分配新的结点
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pNew)
{
printf("动态分配内存失败!\n");
exit(-1);
}
pNew->data = val;
//将新的结点存入p节点的后面
PNODE q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return true;
} */
//我自己写的
bool delete_list(PNODE pHead, int pos, int *pVal) //把位置pos的节点删除,并将删除的值用val返回,pos从1开始
{
int i;
PNODE p, t;
if(pos < 0 || pos > length_list(pHead)) //先判断pos的位置是否有效
{
return false;
}
p = pHead;
for(i = 0; i < pos-1; ++i) //使p指向要删除节点的前一个节点
{
p = p->pNext;
}
*pVal = p->pNext->data;
t = p->pNext;
p->pNext = p->pNext->pNext;
free(t); //释放内存,防止内存泄漏
t = NULL;
return true;
}
/*
//参考郝斌老师写的
bool delete_list(PNODE pHead, int pos, int * pVal)
{
int i = 0;
PNODE p = pHead;
while (NULL!=p->pNext && i<pos-1)
{
p = p->pNext;
++i;
}
if (i>pos-1 || NULL==p->pNext)
return false;
//如果程序能执行到这一行说明p已经指向了第pos-1个结点,并且第pos个节点是存在的
PNODE q = p->pNext; //q指向待删除的结点
*pVal = q->data;
//删除p节点后面的结点
p->pNext = p->pNext->pNext;
//释放q所指向的节点所占的内存
free(q);
q = NULL;
return true;
} */