使用排序C在链表中插入新元素

时间:2016-01-08 23:07:17

标签: c string sorting linked-list strcmp

我在链接列表中将字符串插入正确位置(插入排序)时遇到问题。当我在链接列表中添加一些位置并通过键入“0”结束程序时,程序只显示第一个位置。  我也怀疑“(strcmp(tmp-> ch,new-> ch)> 0)”它正在按照我的想法工作?(将新元素与电流进行比较(我的意思是它应该是'> '或'<'))。 我会非常感谢任何建议;)。我的代码是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_L 30

typedef struct elem{
    char ch[MAX_L];
    struct elem *next;
    struct elem *prev;
}   list_elem;

void add_to_list (list_elem *first, char ch[MAX_L])
{
    list_elem *new=(list_elem*)malloc(sizeof(list_elem));

    strcpy(new->ch, ch);
    list_elem *tmp=first;
    do
    {
        if(tmp->next==NULL)
        {
            tmp->next=new;
            new->prev=tmp;
            new->next=NULL;
        }
        if (strcmp(tmp->ch,new->ch)>0) //guess here should be inserted new element
        {
            new->prev=tmp->prev;
            new->next=tmp;
            tmp->prev=new;
        }
        else
        tmp=tmp->next;

    }while (tmp->next!=NULL);

}


void print_list(list_elem *first)
{
    first=first->next;
    if(first->ch==NULL)
    printf("lista jest pusta!!\n");
    while(first->next!=NULL){
    printf("%s\n",first->ch);
    first=first->next;}
    printf("%s\n",first->ch);
}



int main()
{
    list_elem *first=(list_elem*)calloc(1,sizeof(list_elem));
    first->next=NULL;
    first->prev=NULL;

    char a;
    char ch[MAX_L];
    printf("write ' 0 ' to end program.\n");
    printf("write smth to add it to list: \n");
        while(ch[0]!='0'){
        scanf("%s",&ch);
        add_to_list(first,ch);}
    print_list(first);
    return 0;
}

3 个答案:

答案 0 :(得分:2)

  1. list_elem *first=(list_elem*)calloc(1,sizeof(list_elem));

    您如何知道calloc是否成功? 检查first是否为NULL,然后才能访问first->next

    1. while(ch[0]!='0')

      直到这一点ch数组包含垃圾。那么如何将ch[0]'0'进行比较?

      1. scanf("%s",&ch);

        %s期望char *类型的参数,而&ch的类型为char (*)[30]

        如果用户输入长度为&gt;的字符串,您可能还想避免意外的缓冲区溢出。 sizeof(ch)。指定最大字段宽度以解决此问题。

        1. first=first->next;

        2. print_list()

          在这里你跳过了第一个元素。

          1. if(first->ch==NULL)

            你真的想在这做什么?很可能你想检查字符串first->ch是否为空。如果是,那么检查它的方式。而是检查first->ch[0] == '\0'

            1. while(ch[0]!='0')

              为了检查用户是否输入了0或其他字符串,这是不正确的方法。这将拒绝从0开始的字符串(例如&#34; 0bar&#34;)

              正确的方法是:

              while((ch[0]!='0') || (strlen(ch) > 1))

              1. 在列表

                中插入new节点后,跳出循环
                if (strcmp(tmp->ch,new->ch)>0) 
                {  
                     new->prev=tmp->prev;
                     new->next=tmp;
                     tmp->prev=new;
                }
                

                在插入new节点后,if表达式strcmp(tmp->ch,new->ch)>0将在所有后续循环迭代中保持true,因为我们无法更改tmpnew。所以这将导致无限循环。

                唯一的例外是tmp是最后一个节点。

                解决方案:

                new节点插入列表后立即退出循环。 只需将break;写为上面strcmp if

              2. 中的最后一个语句

答案 1 :(得分:0)

tmp之前插入时,您似乎没有将tmp->prev->next设置为new

为清楚起见:

if (strcmp(tmp->ch,new->ch)>0) //guess here should be inserted new element
    {
        new->prev=tmp->prev;
        new->next=tmp;
        tmp->prev=new;
    }

应该是:

if (strcmp(tmp->ch,new->ch)>0) //guess here should be inserted new element
    {
        tmp->prev->next=new;
        new->prev=tmp->prev;
        new->next=tmp;
        tmp->prev=new;
    }

附注:使用new作为变量名称通常不赞成,因为它不能立即识别为变量,因为大多数程序员都有Java / C#/ C ++等经验new是关键字。

附注2:不要施展malloc。直到最近我读到this堆栈线程时才这样做。这是一个非常好的阅读。

答案 2 :(得分:0)

add_to_list循环中存在问题:

do {
    if(tmp->next==NULL)
    {
        tmp->next=new;
        new->prev=tmp;
        new->next=NULL;
        break; // you must exit here, you don't want to go the "if" below...
    }
    if (strcmp(tmp->ch,new->ch)>0) 
    {
        if( tmp->prev != NULL ) 
        {
            tmp->prev->next = new; // link from previous to the new element 
        }
        new->prev=tmp->prev;
        new->next=tmp;
        tmp->prev=new;
        break; // you should exit here, work is done
    }
    else {
        tmp=tmp->next;
    }
} while (1); // try again

这里也有一个问题:

scanf("%s",&ch); // should be scanf("%s",ch);

对于你的问题:

  

我也怀疑“(strcmp(tmp-&gt; ch,new-&gt; ch)&gt; 0)”它正在工作   我在想什么?

如果你错了,你会按相反的顺序排序,所以它很容易修复。