非循单链表
———-2016年9月17号———–
先来个问题, 如果有知道的, 请在下面留言, 或者发邮件, 先谢谢
问题来自于 链表的 插入, 第二判断 if 处,
while(p != NULL && count < pos-1){
p = p->pNext;
++count;
}
if( count > pos-1 && p == NULL){
return false;
}
为什么, 还要加上一个 p == NULL 的 判断, p->pNext不是已经指向了所插入的位置的了吗????
算法介绍
对单链表进行
列表内容
重要的算法
创建
遍历
插入
删除
排序
简单的算法
求链表长度
判断链表是否为空
取出 链表 特定位置 的 元素
代码实现
第一次实现———-2016年9月10号———–
#include <stdio.h>
#include <stdlib.h> //包含 exit();
#include <malloc.h> //包含 malloc() 函数
#define true 1
#define false 0
typedef int ElemType;
typedef int Status;
//定义 结点类型
typedef struct LNode{
ElemType data; //数据域
struct LNode *pNext; //指针域
}Node, *pLinkList; //用 typedef 将 新定义的 结点类型命名为 Node, 和 指针类型 的 LinkList (没办法, 大多数是这样命名的, 其实我想命名为 pNode)
void createList();
void traverseList(pLinkList pHead);
Status listEmpty(pLinkList pHead);
int listLength(pLinkList pHead);
Status insertList(pLinkList pHead, int pos, ElemType insert_e);
Status deleteList(pLinkList pHead, int pos, ElemType * delete_e);
void sortList(pLinkList pHead);
int main(){
int list_length; //用来存放链表的 结点数, 即 链表长度
ElemType delete_e;
//创建 非循环单链表
pLinkList pHead = (pLinkList)malloc(sizeof(Node));
if(pHead == NULL){
exit(-1);
}
createList(pHead);
//计算链表的 长度
list_length = listLength(pHead);
printf("链表长度为: %d\n\n", list_length);
//如果插入成功, 遍历链表
if( insertList(pHead, 3, 999) ){
traverseList(pHead);
}
//如果删除成功, 遍历链表, 并打印 删除节点处 的 值
if( deleteList(pHead, 3, &delete_e) ){
printf("删除结点的 数据域 值为: %d\n", delete_e);
traverseList(pHead);
}
//将链表排序, 采用冒泡算法
sortList(pHead);
traverseList(pHead);
return 0;
}
//排序算法, 采用冒泡
void sortList(pLinkList pHead){
ElemType temp;
pLinkList p, q;
/*
下面这个段注释 就是按照 冒泡所写的, 因为一开始不会替换, 所以 先把 冒泡写了出来, 在 逐个替换相应 变量
int i, j;
int len = listLength(pHead);
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){
temp = p->data;
p->data = q->data;
q->data = temp;
}
}
}
*/
for(p = pHead->pNext; p->pNext != NULL; p= p->pNext){
for(q = p->pNext; q->pNext != NULL; q= q->pNext){
if(p->data > q->data){
temp = p->data;
p->data = q->data;
q->data = temp;
}
}
}
return;// 以此表明此函数 到此结束
}
//删除算法
void deleteList(pLinkList pHead, int pos, ElemType *delete_e){
int cnt = 0;
pLinkList p, q;
p = pHead;
while( p->pNext != NULL && cnt < pos-1){
p = p->pNext;
++cnt;
}
if(p->pNext == NULL && cnt > pos-1)
return;
q = p->pNext;
*delete_e = q->data;
p->pNext = q->pNext;
return;
}
//插入算法, 整体上 删除和插入的 代码几乎相同
Status insertList(pLinkList pHead, int pos, ElemType insert_e){
int count = 0;
pLinkList p = pHead;
while(p != NULL && count < pos-1){
p = p->pNext;
++count;
}
if( count > pos-1 && p == NULL){
return false;
}
//程序如果执行到这里 表明 链表 不为空, 且 插入位置 正确, 且p->pNext 指向了所插入 位置 的结点处
//新建一个节点
pLinkList pNew = (pLinkList)malloc(sizeof(Node));
if(pNew == NULL){
exit(-1);
}
pNew->data = insert_e;
//将链表指向的 顺序改变
pNew->pNext = p->pNext;
p->pNext = pNew;
return true;
}
//求 链表长度算法
int listLength(pLinkList pHead){
int len = 0;
pLinkList p = pHead->pNext;
while(p!= NULL){
++len;
p = p->pNext;
}
return len;
}
//判断 链表是否为空 可以不写, 因为太简单
Status listEmpty(pLinkList pHead){
if(pHead->pNext == NULL){
return false;
}
return true;
}
//链表遍历算法
void traverseList(pLinkList pHead){
pLinkList p = pHead->pNext;
while(p != NULL){
printf("%d ",p->data);
p = p->pNext;
}
printf("\n\n");
free(p);
return;
}
//创建 链表算法
void createList(pLinkList pHead){
int len;
int i;
ElemType e; //作为临时变量, 用来存储用户输入的值
pLinkList pTail = pHead;
pTail->pNext = NULL;
printf("请输入你需要生成链表的结点个数: len= ");
scanf("%d", &len);
for(i = 0; i < len; ++i){
printf("请输入 第 %d 个结点的值: ", i+1);
scanf("%d", &e);
pLinkList pNew = (pLinkList)malloc(sizeof(Node));
if(pNew == NULL){
exit(-1);
}
pNew->data = e;
pTail->pNext = pNew;
pNew->pNext = NULL;
pTail = pNew;
}
return;
}
第二次实现———-2016年9月17号———–
创建链表的两种—>头插法,尾插法
头插法
头插法, 顾名思义, 后来的 元素, 都在头, 最先来的在 最后一个
pLinkList createList(){
//头插法
int i, len;
pLinkList pHead, p;//定义头结点, 中间结点
pHead = (pLinkList)malloc(sizeof(Node));
//判断一下, 是否内存分配失败, 一般情况下, 可以不写. 但最好还是写上
if(pHead == NULL){ //判断条件可以写成--> if(!pHead)
exit(-1);//调用系统函数, 杀死程序 --> 位于头文件 #include<stdlib.h>
}
pHead->pNext = NULL;
printf("请输入需要创建-->结点的个数: len = ");
scanf("%d", &len);
for(i = 0; i < len; ++i){
p = (pLinkList)malloc(sizeof(Node));
if(p == NULL)
exit(-1);
printf("请输入第%d结点的值: ", i+1);
scanf("%d", &(p->data));
/*
头插和尾插的区别就在这里, 尾插需要 一个结点保留 尾部,(即 尾结点)
而头插就不需要了, 只需要把新来的放在头部,
*/
p->pNext = pHead->pNext;
pHead->pNext = p;
}
return pHead;
}
尾插法
顾名思义: 按照常规的思想来, 先来的就在前面, 后来的都在最后面
pLinkList createList(){
//尾插法
int i, len;
pLinkList pHead, p, pTail;//定义头结点, 中间结点, 尾结点
pHead = (pLinkList)malloc(sizeof(Node));
//判断一下, 是否内存分配失败, 一般情况下, 可以不写. 但最好还是写上
if(pHead == NULL){ //判断条件可以写成--> if(!pHead)
exit(-1);//调用系统函数, 杀死程序 --> 位于头文件 #include<stdlib.h>
}
pTail = pHead;
pTail->pNext = NULL;
printf("请输入需要创建-->结点的个数: len = ");
scanf("%d", &len);
for(i = 0; i < len; ++i){
p = (pLinkList)malloc(sizeof(Node));
if(p == NULL)
exit(-1);
printf("请输入第%d结点的值: ", i+1);
scanf("%d", &(p->data));
pTail->pNext = p;
p->pNext = NULL;
pTail = p;
}
return pHead;
}
链表的排序
一开始, 也不会写, 看看视频, 发现先把 数组排序算法写出来, 然后 逐个替换 为链表里的内容 就行了
我采用的都是 冒泡排序,
数组冒泡:
for(i = 0; i < len - 1; ++i){
for(j = i+1; j < len; ++j){
if(i > j){
temp = i;
i = j;
j = i;
}
}
}
/*
链表排序: 把 i 替换为 p=pHead->pNext, j 相应就替换为 q = p->pNext
循环的条件 就是, 链表是否为空,
++i 相应改为 p = p->pNext
++j 相应改为 q = q->pNext
*/
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){
temp = p->data;
p->data = q->data;
q->data = temp;
}
}
}
最后删去多余的代码,
for(p = pHead->pNext; p != NULL; p = p->pNext){
for(q = p->pNext; q != NULL; q= q->pNext){
if(p->data > q->data){
temp = p->data;
p->data = q->data;
q->data = temp;
}
}
}
具体代码
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define true 1
#define false 0
typedef int ElemType;
//定义结点类型
typedef struct Node{
ElemType data;//数据域
struct Node *pNext;//指针域
} Node, *pLinkList;
pLinkList createList();
void traverseList(pLinkList pHead);
void insertList(pLinkList pHead, int pos, ElemType insert_e);
void deleteList(pLinkList pHead, int pos, ElemType *delete_e);
void sortList(pLinkList pHead);
int main() {
ElemType delete_e = 0;//因为下面会将它的地址作为参数, 所以这里做好将它初始化, 防止出现意外情况
pLinkList pHead;
pHead = createList();
printf("链表为: ");
traverseList(pHead);
insertList(pHead, 3, 99);
printf("插入后: ") ;
traverseList(pHead);
deleteList(pHead, 3, &delete_e);
printf("删除后: ") ;
traverseList(pHead);
sortList(pHead);
printf("排序后: ");
traverseList(pHead);
return 0;
}
void sortList(pLinkList pHead){
pLinkList p, q;
ElemType temp;
for(p = pHead->pNext; p != NULL; p = p->pNext){
for(q = p->pNext; q != NULL; q= q->pNext){
if(p->data > q->data){
temp = p->data;
p->data = q->data;
q->data = temp;
}
}
}
return;
}
void deleteList(pLinkList pHead, int pos, ElemType *delete_e){
int cnt;
pLinkList p, q;
p = pHead;
while( p->pNext != NULL && cnt < pos-1){
p = p->pNext;
++cnt;
}
if(p == NULL && cnt > pos-1)
return;
q = p->pNext;
*delete_e = q->data;
p->pNext = q->pNext;
return;
}
void insertList(pLinkList pHead, int pos, ElemType insert_e){
int cnt = 0;//用来计数
pLinkList p, q;
p = pHead;
//首先判断链表是否为空
while(p->pNext != NULL && cnt < pos-1){
p = p->pNext;
++cnt;
}//如果循环结束, 那么 cnt 的值也就是p指向了第几个结点值
/*
这个判断, 有两个作用
1, 判断 pos 的值是否正确, (如 为负, 或 比链表的 实际长度 len 大 1, 则结束本函数 )
2, 判断 此位置的 p 是否为空,
*/
if(cnt > pos-1 && p == NULL){
return;
}
//如果程序执行到这一步, 那 p->pNext 已经指向了 所插入的位置
q = (pLinkList)malloc(sizeof(Node));
if(q == NULL)
exit(-1);
q->data = insert_e;
q->pNext = p->pNext;
p->pNext = q;
return;
}
void traverseList(pLinkList pHead){
pLinkList p = pHead->pNext;
while(p != NULL){ //循环条件也可写成--> while(!p)
printf("%d ", p->data);
p = p->pNext;
}
printf("\n\n"); //结束时,换行
return;
}
pLinkList createList(){
//尾插法
int i, len;
pLinkList pHead, p, pTail;//定义头结点, 中间结点, 尾结点
pHead = (pLinkList)malloc(sizeof(Node));
//判断一下, 是否内存分配失败, 一般情况下, 可以不写. 但最好还是写上
if(pHead == NULL){ //判断条件可以写成--> if(!pHead)
exit(-1);//调用系统函数, 杀死程序 --> 位于头文件 #include<stdlib.h>
}
pTail = pHead;
pTail->pNext = NULL;
printf("请输入需要创建-->结点的个数: len = ");
scanf("%d", &len);
for(i = 0; i < len; ++i){
p = (pLinkList)malloc(sizeof(Node));
if(p == NULL)
exit(-1);
printf("请输入第%d结点的值: ", i+1);
scanf("%d", &(p->data));
pTail->pNext = p;
p->pNext = NULL;
pTail = p;
}
return pHead;
}
/*
pLinkList createList(){
//头插法
int i, len;
pLinkList pHead, p;//定义头结点, 中间结点
pHead = (pLinkList)malloc(sizeof(Node));
//判断一下, 是否内存分配失败, 一般情况下, 可以不写. 但最好还是写上
if(pHead == NULL){ //判断条件可以写成--> if(!pHead)
exit(-1);//调用系统函数, 杀死程序 --> 位于头文件 #include<stdlib.h>
}
pHead->pNext = NULL;
printf("请输入需要创建-->结点的个数: len = ");
scanf("%d", &len);
for(i = 0; i < len; ++i){
p = (pLinkList)malloc(sizeof(Node));
if(p == NULL)
exit(-1);
printf("请输入第%d结点的值: ", i+1);
scanf("%d", &(p->data));
p->pNext = pHead->pNext;
pHead->pNext = p;
}
return pHead;
}
*/
仅供参考 ,有错误望指出.
有大神路过请指点一下。 菜鸟求飞 !!!
有什么疑问 也可以在 下边 提问 ! (有点托大了)或者发邮件
E-Mail:[email protected]