| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2165 人关注过本帖, 4 人收藏
标题:詳解鏈表
取消只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
11樓的代碼,給出了單向鏈表生成、插入元素、刪除元素的操作實現,僅供參考。

授人以渔,不授人以鱼。
2015-03-17 18:01
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
回复 16楼 wube
下次附英文好了。老實説,這才是最成問題的,臺陸事實分裂多年,文化愈益分離,縱然字型相同,然而名詞術語不同,則本質屬於不同的文化,一個世紀過去,獨立的民族足以成型,衹有大陸仍自欺欺人,說什麽時間充足,優勢在自己一邊。正如魯迅文章中所說,一蟹不如一蟹,最糟糕的還是自我陶醉,不知危險之將至。

[ 本帖最后由 TonyDeng 于 2015-3-17 20:30 编辑 ]

授人以渔,不授人以鱼。
2015-03-17 19:53
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
在這裏順便說一下我的字體問題:

1.正體字是中華民族的傳統字型,秦始皇剿滅六國之後,書同文,鑄造了中國文化強大的融合力,從此中華民族不易崩潰,文化得以延續,皆拜書同文之故(並非語同音)。當今之下,凡是炎黃子孫,均須認識正體字,方得以傳承民族精神,否則視祖宗猶如外族,連族譜都讀不明白,祖父輩名字都念不出來,那就丟人到家了。認識正體字,不是說非要寫,但至少會認,說認不得是講不過去的。

2.我在臺式機上用正體字,在手機時會用簡化字,看到字體,就知道我用什麽上網,手機打字不方便,那時不會說很多話,字體是一種暗示,表明我的狀態。

3.凡是我自己寫的文字,均是此等字體,黏貼的不是,一看就知道。

授人以渔,不授人以鱼。
2015-03-17 20:06
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
更新
1.修復刪除結點是鏈頭時崩潰的錯誤,即可以刪除鏈頭,轉移下一個元素爲鏈頭
2.刪除結點函數的返回値修改爲返回鏈頭

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

// 結點數據結構
struct Node
{
    int   Value;                // 數據的内容(按需要可爲任何數據類型)
    Node* Next;                 // 數據的地址
};

// 函數原型
void Pause(void);
Node* InsertNode(Node* to, Node* from);
Node* DeleteNode(Node** head, Node* node);
void ShowData(const Node* node);
void ListLinkData(const Node* head);
void FreeLink(Node* head);

// 程序主入口
int main(void)
{
    Node* linkHead = NULL;

    printf_s("從數組中提取數據生成鏈表\n");
    int data[] = { 1, 2, 3, 4, 5 };
    Node* node = linkHead;
    for (int index = 0; index < _countof(data); ++index)
    {
        Node* p = (Node*)calloc(1, sizeof(Node));
        p->Value = data[index];
        node = InsertNode(node, p);
        if (linkHead == NULL)
        {
            linkHead = node;
        }
    }
    ListLinkData(linkHead);
    putchar('\n');

    printf_s("在第2個元素後面插入一個新的元素\n");
    node = (Node*)calloc(1, sizeof(Node));
    node->Value = 10;
    InsertNode(linkHead->Next, node);
    ListLinkData(linkHead);
    putchar('\n');

    printf_s("刪除剛才插入元素的下一個\n");
    DeleteNode(&linkHead, node->Next);
    ListLinkData(linkHead);
    putchar('\n');

    FreeLink(linkHead);
   
    Pause();
    return EXIT_SUCCESS;
}

// 暫停等待用戶按鍵
void Pause(void)
{
    printf_s("\n按任意鍵繼續...");
    _getch();
}

// 將form元素插入在to元素後,如果to爲NULL,則將from創建爲鏈頭,返回from
Node* InsertNode(Node* to, Node* from)
{
    Node* last = NULL;

    if (to != NULL)
    {
        if (to->Next != NULL)
        {
            last = to->Next;
        }
        to->Next = from;
        from->Next = last;
    }

    return from;
}

// 刪除指定的結點node,返回鏈頭
// 對單向鏈表,爲了查尋前面的元素,必須從鏈表開始檢索,所以需要傳入鏈頭
Node* DeleteNode(Node** head, Node* node)
{
    if (node == *head)
    {
        *head = node->Next;
    }
    else
    {
        Node* previous = NULL;      // 前一個元素
        Node* p = *head;            // 遍歷指針
        while ((p != NULL) && (p != node))
        {
            previous = p;
            p = p->Next;
        }
        previous->Next = node->Next;
    }
    free(node);

    return *head;
}

// 輸出結點的信息
void ShowData(const Node* node)
{
    printf_s("Adress = %p, Value = %d, Next = %p\n", node, node->Value, node->Next);
}

// 從指定的結點開始列出鏈表數據
void ListLinkData(const Node* head)
{
    if (head != NULL)
    {
        const Node* node = head;
        do
        {
            ShowData(node);
            node = node->Next;
        } while (node != NULL);
    }
}

// 刪除並釋放從指定節點開始的鏈表數據
void FreeLink(Node* head)
{
    if (head != NULL)
    {
        Node* next;
        do
        {
            next = head->Next;
            free(head);
            head = NULL;
            head = next;
        } while (next != NULL);
    }
}



授人以渔,不授人以鱼。
2015-03-17 23:53
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
scanf()函数族,即包括fscanf()、sscanf()、scanf_s()等,其返回值是成功读取的项数。比如scanf("%d%d", &x, &y),试图读取2项数据,但实际上由于各种原因(最典型是用户输入可能不合要求),造成实际操作成功少于2项,如只读到1个x,y读不成功(输入了字母无法转换为数值),那么函数的返回值就是1,当成功完成全部任务时,它的返回值应是2,此时表示操作百分百正确。我的循环while(scanf("%d", &value) != 1),就是当且仅当scanf()函数成功读取了1个整数时才结束循环,此时读取失败的返回值是0。

之所以要写这个函数,是因为程序要求用户输入整数,而他可能不会那么老实,这时就反复循环强制他输入正确为止,否则程序不会往下继续执行。很多初学者写程序,以为写了一个scanf(),用户就会输入正确,那是想当然,那不过是由于程序是你自己写的、自己知道规避错误,但若是交给用户实用的程序,这样就是漏洞,因为那时用户就算输入了垃圾数据,你的程序也照往下执行,那就是经常运行时莫名其妙崩溃的原因。

另外,良好的编程方式,当人机交互输入时,最好只用1项scanf(),此时代码可以即时监测是哪一项输入不正确,从而有针对性地反应。见过有人用scanf()一气接收10多项数据的,那是没实践经验的表现,肯定是从来没遇到过现实输入千奇百怪而需要追踪哪项数据出错情形的。你一项一项逐个输入、逐个提示,那么错在哪信息也很明确,不用乱猜。现实的经验其实是:不要以为把代码写得很短、很紧凑是本事,那往往是不实用的,切身处地站在用户的角度去审查自己的程序,这是首先要培养的世界观。你说改了测试能通过,就是没有想到输入字母等数字之外的东西来测试,自然不知道这段代码应对什么问题。

授人以渔,不授人以鱼。
2015-08-07 03:10
快速回复:詳解鏈表
数据加载中...
 
   



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

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