c语言中链表的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言中链表的问题相关的知识,希望对你有一定的参考价值。

#include"stdio.h"
////////////定义的数据//////////////////
typedef struct x

int num;
int age;
char name[20];
int sex :1;
x *next;
DATA;
////////////////////////////////////////
/* 定义的函数 */
//////////////链表的初始化//////////////
DATA *StartList()

DATA *p=new DATA;
p->next=NULL;
p->num=1;
DATA *h=p;
int n;
while(1)

printf("please input data (age,name,sex):");
scanf("%d%s%d",p->age,p->name,p->sex);
p->next=new DATA;
p=p->next;
printf("Do you want to quit this function(Y/N)\n Y is 1,N is 0");
scanf("%d",&n);
if(n==1) break;

return h;

////////////////////////////////////////
////////////////////////////////////////
void main()

StartList();

我做了个链表程序,正处于调试状态,调试StartList,编译器没出错,程序能正常运行,但是中途会报错,你们可以调试一下,出现错误。
请问我的代码出错了吗?哪里出错?

////////////定义的数据//////////////////
typedef struct x

int num;
int age;
char name[20];
int sex :1; //你这是什么东西?
x *next; //你这是什么数据类型?
DATA;
参考技术A p->next=new DATA;
p=p->next;在前面没有新建节点,你这样怎么形成链表呢?你不是始终就只有一个结构吗。
基本链表创建一般是:创建一个节点;用这个把它串上去p->next=new DATA;p=p->next;然后在创建节点,再串上去;追问

.............p->new=new DATA是开辟了DATA数据的新空间,你这还不清楚吗,p=p->new把p指向那个空间,之后循环重复开辟空间,和MALLOC这样开辟空间差不多

追答

孤陋寡闻了 没听说过 也没用过 不好意思啊

参考技术B 具体会出什么错啊,下面是看到的几个问题。
#include"stdio.h"
////////////定义的数据//////////////////
typedef struct x

int num;
int age;
char name[20];
int sex :1;
x *next;
DATA;
////////////////////////////////////////
/* 定义的函数 */
//////////////链表的初始化//////////////
DATA *StartList()

DATA *p=new DATA;
p->next=NULL;
p->num=1;
DATA *h=p;
int n;
while(1)

printf("please input data (age,name,sex):");
scanf("%d%s%d",p->age,p->name,p->sex);
//上句建议修改成scanf("%d,%d,%s",p->age,p->sex,p->name);
//这里一直未对num进行操作
p->next=new DATA; //最后一次申请的结构没有初始化,其中的next为野指针
p=p->next;
printf("Do you want to quit this function(Y/N)\n Y is 1,N is 0");
scanf("%d",&n);
if(n==1) break;

return h;
//链表结尾访问会出问题:你无法判断它是否是链表之尾,顺着next下去会乱
////////////////////////////////////////
////////////////////////////////////////
void main()

StartList();
追问

那你认为该怎么个修改法

追答

DATA *StartList()

DATA *p=new DATA;
DATA *pLast; // =====================================================
pLast=p; // =====================================================
p->next=NULL;
p->num=0;
DATA *h=p;
int n;
while ( 1 )

printf("please input data (age,name,sex):");
scanf("%d,%d,%s",p->age,p->sex,p->name); // ===========================
p->num=pLast->num+1; // 记录序号====================================
pLast=p; // =======================================================
p->next=new DATA;
p=p->next;
printf("Do you want to quit this function(Y/N)\n Y is 1,N is 0");
scanf("%d",&n);
if ( n==1 ) pLast->next=NULL; delete p; break; // =======================

return h;

以后访问链表时发现p->next==NULL时表示链表访问完毕。

C中链表的插入排序?

【中文标题】C中链表的插入排序?【英文标题】:Insertion sort on linked list in C? 【发布时间】:2013-04-04 07:30:12 【问题描述】:

我尝试搜索与我类似的问题,但没有找到太多帮助。

我有一个此类结构的链接列表:

struct PCB 
    struct PCB *next;
    int reg1, reg2;
;

我首先创建了 10 个以这种方式链接在一起的 PCB 结构:

for(i=20;i<=30;i++) 
        curr = (struct PCB *)malloc(sizeof(struct PCB));
        curr->reg1 = i;
        curr->next  = head;
        head = curr;
    

然后我需要再创建 20 个 PCB 结构,但它们的 reg1 值需要使用 rand() 生成。我目前正在这样做:

for (j = 0;j<20;j++) 
        curr = (struct PCB *)malloc(sizeof(struct PCB));
        curr->reg1 = rand()%100;
        curr->next  = head;
        head = curr;
    

但是,当将这些 PCB 结构插入到带有随机 reg1 值的链表中时,我需要将它们按顺序插入到链表中(插入排序)。仅在单链接链表中解决此问题的最佳方法是什么?谢谢

编辑: 我现在正在跟踪第一个创建的结构,以便能够从头开始循环遍历链表:

// create root struct to keep track of beginning of linked list
root = (struct PCB *)malloc(sizeof(struct PCB));
root->next = 0;  
root->reg1 = 20;

head = NULL;

// create first 10 structs with reg1 ranging from 20 to 30
for(i=21;i<=30;i++) 
    curr = (struct PCB *)malloc(sizeof(struct PCB));
    // link root to current struct if not yet linked
    if(root->next == 0)
        root->next = curr;
    
    curr->reg1 = i;
    curr->next  = head;
    head = curr;

然后,当我创建另外 10 个需要插入排序的 PCB 结构时:

// create 20 more structs with random number as reg1 value
    for (j = 0;j<20;j++) 
        curr = (struct PCB *)malloc(sizeof(struct PCB));
        curr->reg1 = rand()%100;
        // get root for looping through whole linked list
        curr_two = root;
        while(curr_two) 
            original_next = curr_two->next;
            // check values against curr->reg1 to know where to insert
            if(curr_two->next->reg1 >= curr->reg1) 
                // make curr's 'next' value curr_two's original 'next' value
                curr->next = curr_two->next;
                // change current item's 'next' value to curr
                curr_two->next = curr;
            
            else if(!curr_two->next) 
                curr->next = NULL;
                curr_two->next = curr;
            
            // move to next struct in linked list
            curr_two = original_next;
        
        head = curr;
    

但这立即使我的程序崩溃。

【问题讨论】:

【参考方案1】:

“最佳”方法可能是为插入实现一个新功能。此函数将遍历列表,直到找到next 节点值小于或等于您要插入的节点的节点,然后将新节点放在next 节点之前。


这个功能怎么样:

void insert(struct PCB **head, const int reg1, const int reg2)

    struct PCB *node = malloc(sizeof(struct PCB));
    node->reg1 = reg1;
    node->reg2 = reg2;
    node->next = NULL;

    if (*head == NULL)
    
        /* Special case, list is empty */
        *head = node;
    
    else if (reg1 < (*head)->reg1)
    
        /* Special case, new node is less than the current head */
        node->next = *head;
        *head = node;
    
    else
    
        struct PCB *current = *head;

        /* Find the insertion point */
        while (current->next != NULL && reg1 < current->next->reg1)
            current = current->next;

        /* Insert after `current` */
        node->next = current->next;
        current->next = node;
    

你可以这样称呼它:

insert(&root, rand() % 100, 0);

【讨论】:

但是我不需要双链接才能在我要插入的位置之前和之后获取节点吗? 不需要。在查看一个节点时,还要查看下一个节点。因此,对于每次迭代,您都持有两个引用:一个用于您正在查看的当前引用,另一个用于链接中的下一个引用。然后将这两个与您要插入的节点进行比较。 当 node->next == 0 或 node->next->key > key 时插入节点后 真的有人这样写代码吗?您不需要所有这些额外的情况......只需保留一个指向要插入的链接而不是节点的指针;最初是 &head,然后是 &node->next 在每次迭代之后。 对于那些想知道的人,是的,我的编程很冗长。当我认为其他人阅读和理解不会令人费解或更难时,我会进行概括。我相信编译器会做出比以往任何时候都更优化的代码,所以我更喜欢编写简单易读的小块,让编译器做它想做的任何转换。不,有时它不是最佳的,但至少我不需要花 15 分钟(或更多)来理解我的代码一年。【参考方案2】:

这是@Joachim 的简化版:

void insert(struct PCB **head, const int reg1, const int reg2)

    struct PCB *new ;
        /* Find the insertion point */
    for (       ;*head; head = & (*head)->next)
    
        if ((*head)->reg1 > reg1) break;
    

    new = malloc(sizeof *new );
    new->reg1 = reg1;
    new->reg2 = reg2;
    new->next = *head;
   *head = new;

这个想法很简单:不需要任何特殊情况,无论如何: 需要更改一个指针,这可能是根指针、尾指针或 LL 中间的某个指针。在任何/每种情况下:

新节点实际上窃取这个指针: 它使它指向它自己采用前一个值作为后继值(将其分配给它的-&gt;next 指针。

【讨论】:

但是嘿,我只复制了@Joachim 的评论!

以上是关于c语言中链表的问题的主要内容,如果未能解决你的问题,请参考以下文章

c语言中创建动态链表

C中链表的插入排序?

C语言从文件中读出数据构造成链表

比较 C 中链表中的值时的问题

充电站 | 内核链表的妙用

C ++中链表实现中的分段错误