| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1941 人关注过本帖, 1 人收藏
标题:分享:简单的链表操作
只看楼主 加入收藏
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
结帖率:95.65%
收藏(1)
 问题点数:0 回复次数:20 
分享:简单的链表操作
链表的所有操作,无论插入,还是删除节点,还是逆序,都是对next值的修改!!!!!!!!!
再此,根指针是一个特例,原因在于,函数无法访问根指针,因此这里需要二级指针。
当然,解决函数无法访问根指针有多个办法,第一,传递一个完整的节点。第二,全局变量。第三,二级指针。
这样一看,二级指针可谓最优化选择。



至于双链表,我还有一个最后的查找没有完成。悲剧。因为双链表,可以从多个方向进行遍历,所以一直没有完成。

程序代码:
//调用示例:
#include <stdio.h>
#include "List.h"

int
main( void )
{
    Node *Root;
    Node *P;
    int value;

    Root = NULL;

    while( 1 == scanf( "%d", &value ) )//插入测试,升序。如要按照输入顺序插入,那么需要删除InsertNode  while循环中的值判断
        InsertList( &Root, value );
    PrintList( Root, ' ' );//打印测试。该函数接受一个节点指针和一个字符,用来作为打印的分割符。
    printf( "\n" );

    getchar();

    while( 1 == scanf( "%d", &value ) )
        DeleteNode( &Root, value );//删除节点,接受一个节点指针和一个值,注意,你需要传递该指针本身的地址。
    PrintList( Root, ' ' );
    printf( "\n" );

    Root = ReverseList( Root );//逆序。返回新链表的指针。这里可以也可以用二级指针来做到没有返回值,但是不够灵活。
    PrintList( Root, ' ' );
    printf( "\n" );

    getchar();
    while( 1 == scanf( "%d", &value ) )
    {
        P = FindNode( Root, value );
        printf("%d",P->Value);
    }

    DeleteList( &Root );//删除链表。

    return 0;
}


程序代码:
#ifndef List_H
#define List_H
typedef struct NODE {
    int Value;
    struct NODE *Next;
}Node; 

void 
PrintList( Node *RootP,char Spacech );
int 
InsertList( Node **RootP, int value );
void 
DeleteList( Node **RootP );
void 
DeleteNode( Node **RootP, int value );
Node *
FindNode( Node *Root, int value );
Node *
ReverseList( Node *first );
#endif



程序代码:
#include <stdio.h>
#include <stdlib.h>
#include "List.h"

int 
InsertList( Node **RootP, int value )
{
    Node *NewCell;
    Node *Current;

    while( NULL != ( Current = *RootP ) && value > Current->Value )
        RootP = &Current->Next;//Current往前遍历,用RootP来保存之前的Next值,这样,当Current找到插入点的时候,RootP就可以告诉我们,那个Next需要修改
                               //至于链表为空,还是插入点为头部,尾部,这些无需考虑,因为newcell->next一定是指向current,
    
    NewCell = (Node *)malloc( sizeof(Node) );
    if( NULL == NewCell )
        return 0;
    NewCell->Value = value;
    NewCell->Next = Current;
    *RootP = NewCell;

    return 1;

}

void 
DeleteNode( Node **RootP , int value )
{
    Node *Current;

    while( NULL != ( Current = *RootP ) && value != Current->Value )
        RootP = &Current->Next;//如上

    if( NULL == Current )
        return;
    *RootP = Current->Next;
    free( Current );
}

void 
PrintList( Node *RootP, char Spacech )
{
    Node *Current;

    while( NULL != ( Current = RootP ) )
    {
        printf("%d%c",Current->Value,Spacech);
        RootP = Current->Next;
    }
}


void 
DeleteList( Node **RootP )
{
    Node *Current;
    Node *Temp;

    Current = *RootP;
    *RootP = NULL;//根指针设置为NULL

    while( NULL != Current )
    {
        Temp = Current->Next;//Temp保存下一节点
        free( Current );//释放当前节点
        Current = Temp;//更新Current的值
    }
}


Node *
FindNode( Node *Root, int value )
{
    Node *Next;

    while( NULL != ( Next = Root ) && Next->Value != value )
        Root = Next->Next;

    return Next;
}

Node *
ReverseList( Node *first )
{
    Node *current;
    Node *next;

    for( current = NULL; NULL != first; first = next )
    {//first往前遍历,next保存下一节点。这样,first的值就是需要修改的值。
        next = first->Next;
        first->Next = current;
        current = first;
    }

    return current;
}



[此贴子已经被作者于2017-3-21 20:38编辑过]

搜索更多相关主题的帖子: color 
2017-03-21 19:51
yangfrancis
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:贵宾
威 望:141
帖 子:1510
专家分:7661
注 册:2014-5-19
收藏
得分:0 
没注。有点不好懂。还是顶了。
2017-03-21 20:06
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
标注

DO IT YOURSELF !
2017-03-21 20:08
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 2楼 yangfrancis
我在帖子的最开始写了啊。一切操作都是对Next的修改,函数中的东西无非是遍历,查找。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-03-21 20:09
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 3楼 wp231957
我在帖子的最开始写了啊。一切操作都是对Next的修改,函数中的东西无非是遍历,查找。

09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-03-21 20:09
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
回复 5楼 renkejun1942
我不是这个意思  我的意思是  标注==收藏

我现在就对这些next没有搞懂  我又不想背代码  要说实现神马功能 那好办 网上现成的代码 N多 改改就能用

DO IT YOURSELF !
2017-03-21 20:12
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 6楼 wp231957
好吧,我加上一些必须的注释。
还是帖子最开始的话了,一切操作都是对Next的修改。

Next似乎是一个约定,指向链表下一节点的指针应该命名为Next。(反正我在大部分的书上看到的命名都是Next)。
双链表的指针,一般命名为prev和next,我曾经命名为left和right,被吐槽了半天。

[此贴子已经被作者于2017-3-21 20:41编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-03-21 20:14
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
以下是引用renkejun1942在2017-3-21 20:14:21的发言:

Node *
ReverseList( Node *first )
{
    Node *current;
    Node *next;

    for( current = NULL; NULL != first; first = next )
    {//first往前遍历,next保存下一节点。这样,first的值就是需要修改的值。
        next = first->Next;
        first->Next = current;
        current = first;
    }

    return current;
}
你这个current 返回的是不是 所谓的第一节点啊  而不是head节点

DO IT YOURSELF !
2017-03-21 20:41
renkejun1942
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:不是这样
等 级:贵宾
威 望:33
帖 子:1645
专家分:5297
注 册:2016-12-1
收藏
得分:0 
回复 8楼 wp231957
在逆序函数中,最后的时候current指向的是最后一个节点。
但是在遍历的过程中,所有节点的next都被修改,所以,它也就是第一节点。
是的,他是第一节点,不是根指针。这里用的是一级指针,在函数中是无法访问根指针的。

[此贴子已经被作者于2017-3-21 20:44编辑过]


09:30 05/21 种下琵琶种子,能种活么?等待中……
21:50 05/27 没有发芽。
20:51 05/28 没有发芽。
23:03 05/29 没有发芽。
23:30 06/09 我有预感,要发芽了。
2017-03-21 20:42
wp231957
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:神界
等 级:贵宾
威 望:423
帖 子:13688
专家分:53332
注 册:2012-10-18
收藏
得分:0 
这样虽然可以全部输出  可是却是多了一些东西  
程序代码:
#include <stdio.h>
#include <malloc.h>

#define N 8

typedef struct date
{
    unsigned int month;
    unsigned int day;
    unsigned int year;
    struct date* next;
}tdate,*pdate;


pdate linkcre(void)
{
    pdate head,pfirst,psecond;
    tdate cr[8]=
    {
        {10,10,2000},{11,11,2012},{05,05,2005},{01,01,2006},{12,30,2016}
        ,{01,01,2005},{02,02,2008},{03,03,2009}
    };
    pfirst=(pdate)malloc(sizeof(tdate));
    head=pfirst;
    psecond=pfirst;
    int i;
    for(i=0;i<N;i++)
    {
        pfirst=(pdate)malloc(sizeof(tdate));
        pfirst->month=cr[i].month;
        pfirst->day=cr[i].day;
        pfirst->year=cr[i].year;
        pfirst->next=NULL;
        psecond->next=pfirst;
        psecond=pfirst;
    }
    return head;
}

void prnlist(pdate head)
{
    pdate pfirst=head->next;
    while(pfirst!=NULL)
    {
        printf("%6u%4u%4u\n",pfirst->year,pfirst->month,pfirst->day);
        pfirst=pfirst->next;
    }
}

void prnlist2(pdate head)
{
    pdate pfirst=head;
    while(pfirst!=NULL)
    {
        printf("%6u%4u%4u\n",pfirst->year,pfirst->month,pfirst->day);
        pfirst=pfirst->next;
    }
}



pdate reverselist2(pdate first )
{
    pdate current;
    pdate next;

    for( current = NULL; NULL != first; first = next )
    {//first往前遍历,next保存下一节点。这样,first的值就是需要修改的值。
        next = first->next;
        first->next = current;
        current = first;
        //printf("next=%p  first=%p  first->next=%p \n",next,first->next,current);
    }
    return current;
}



int main(int argc, char* argv[])
{
    pdate  head;
    head=linkcre();
    printf("////////////正常输出示例//////////////////\n");
    prnlist(head);
    head=reverselist2(head);
    printf("////////////逆序输出示例//////////////////\n");
    prnlist2(head);
    free(head);
    return 0;
}

/*
////////////正常输出示例//////////////////
  2000  10  10
  2012  11  11
  2005   5   5
  2006   1   1
  2016  12  30
  2005   1   1
  2008   2   2
  2009   3   3
////////////逆序输出示例//////////////////
  2009   3   3
  2008   2   2
  2005   1   1
  2016  12  30
  2006   1   1
  2005   5   5
  2012  11  11
  2000  10  10
345281684534528168453452816845
*/



DO IT YOURSELF !
2017-03-21 20:44
快速回复:分享:简单的链表操作
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.161210 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved