线性结构--->单链表实现


非循单链表

———-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]

猜你喜欢

转载自blog.csdn.net/qq_32603745/article/details/52495457