因为一些事情耽误,好久没写文章了(整的跟写过好多篇似的,哈哈哈)。进入正题!
那么下面我讲几个对我而言容易迷糊的点:
首先我们在看这个的时候,一定要注意我们这个链表是含有头节点的!!!在很多地方实现的时候都要考虑进去。
在void sort(PNODE pHead);部分我们采取的是冒泡排序的思想,并且是从小到大进行排序的。我们在看着部分的时候可以对照一下原先的冒泡排序,更容易理解。
在各个功能中我们要注意是否有特殊情况(special circumstances)
在bool insert(PNODE pHead,int pos,int val)中
pNew->data=val;
PNODE q=p->pNext;
p->pNext=pNew;
pNew->pNext=q;要是不太清楚,我们可以画个图片:
以下是链表的全部实现。
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
//该链表含有头节点!!!
typedef struct Node {
int data;
struct Node* pNext;
}NODE,*PNODE;
//函数声明
PNODE creat_list(void);//创建一个空链表
void traverse(PNODE);//遍历链表
bool is_empty(PNODE);//判断是否为空
int length_list(PNODE);//链表长度
bool insert(PNODE,int,int);//在第pos个节点的前面插入一个值为val的节点
bool delete_list(PNODE,int,int*);
void sort(PNODE pHead);
int main(void) {
PNODE pHead = NULL;
int val;
//creat_list功能创建一个非循环单链表
pHead = creat_list();//创建一个非循环单链表,并将该链表的头节点的地址付给pHead
traverse(pHead);//遍历
//判断链表是否为空
if (is_empty(pHead))
printf("链表为空!\n");
else
printf("链表不为空!\n");
//链表的有效长度
int len = length_list(pHead);
printf("链表长度是%d\n", len);
//排序
sort(pHead);
traverse(pHead);
//插入
insert(pHead, 3, 33); //在pHead所指向链表的第pos个节点的前面插入一个新的节点
traverse(pHead);
//节点的删除
//4表示删除第四个元素的下标(从1开始)
if (delete_list(pHead, 4, &val))//val用来保存所删除节点的值(数据域)
printf("删除成功,您删除的元素是:%d\n", val);
else
printf("删除失败!\n");
traverse(pHead);
return 0;
}
PNODE creat_list(void) {
int i,len,val;
PNODE pHead=(PNODE)malloc(sizeof(NODE));
//special circumstances
if(pHead==NULL) {
printf("分配失败!\n");
exit(-1);//程序运行成功会返回 0 值,而非零值表示程序出现了异常或错误
}
//尾插法:
PNODE pTail=pHead;
pTail->pNext=NULL;
printf("请输入要生成链表的长度:");
scanf("%d",&len);
for(int i=0;i<len;i++) {
printf("请输出第%d个节点的值:",i+1);
scanf("%d",&val);
PNODE pNew=(PNODE)malloc(sizeof(NODE));
if(pHead==NULL) {
printf("分配失败!\n");
exit(-1);
}
pNew->data=val;
//尾插法:
pTail->pNext=pNew;
pTail=pNew;
pNew->pNext=NULL;
}
return pHead;
}
void traverse(PNODE pHead) {
PNODE p=pHead->pNext;//p指向第一个有效节点
while(p!=NULL) {
printf("%d ",p->data);
p=p->pNext;
}
printf("\n");
return;
}
bool is_empty(PNODE pHead) {
if(pHead->pNext==NULL) {
return true;
} else {
return false;
}
}
int length_list(PNODE pHead) {
PNODE p=pHead->pNext;
int len=0;
while(p!=NULL) {
len++;
p=p->pNext;
}
return len;
}
bool insert(PNODE pHead,int pos,int val){
int i=0;
PNODE p=pHead;
while(p!=NULL && pos-1>i) {//定位到第pos-1个节点,因为p最初指向的是pHead头节点!!!(存放无效数据的)
p=p->pNext;
i++;
}
//special circumstances
if(i>pos-1 || p==NULL) {
return false;
}
PNODE pNew=(PNODE)malloc(sizeof(NODE));
if(pNew==NULL) {
printf("分配失败!\n");
exit(-1);
}
pNew->data=val;
PNODE q=p->pNext;
p->pNext=pNew;
pNew->pNext=q;
return true;
}
bool delete_list(PNODE pHead,int pos,int* pVal) {//*pVal存放的是删除节点的data
int i=0;
PNODE p=pHead;
//找到第pos-1个节点
while(p->pNext!=NULL && pos-1>i) {
i++;
p=p->pNext;
}
PNODE q=p->pNext;//将q定位到第pos个节点位置
//保存第pos个节点位置的data
*pVal=q->data;
//删除
p->pNext=q->pNext;
//释放q的内存空间
free(q);
q=NULL;
return true;
}
void sort(PNODE pHead) {
//升序排序
//bubble sort
int i,j,t;//交换变量的中间值
int len=length_list(pHead);
PNODE p;
PNODE q;
for(i=0,p=pHead->pNext;i<len-1;i++,p=p->pNext) {//p=pHead->pNext:让p指向第一个有效节点(首节点)
for(j=i+1,q=p->pNext;j<len;j++,q=q->pNext) {
if(p->data > q->data) {//类似于a[j]>a[j+1]
t=p->data;
p->data=q->data;
q->data=t;
}
}
}
return;
}