C 如何在运行时创建和排序单链表?
我试图通过读取文本文件创建一个链表,并以升序输出读取的单词及其计数 除了尝试在运行时对节点进行排序外,一切正常 首先,我尝试了冒泡排序,但我无法理解链表开头部分的逻辑 第二,我一直试着比较x->next的计数,直到我发现一个比我想推回的大。然后我交换它们。我使用了许多指针,但有时可以工作,但在某些边缘情况下失败 我本应该保存一些代码,让人们指出我的逻辑缺陷,但我只是有点沮丧,试图从头开始 有人能提供一些好的逻辑或显式伪逻辑吗?多谢各位C 如何在运行时创建和排序单链表?,c,pointers,linked-list,C,Pointers,Linked List,我试图通过读取文本文件创建一个链表,并以升序输出读取的单词及其计数 除了尝试在运行时对节点进行排序外,一切正常 首先,我尝试了冒泡排序,但我无法理解链表开头部分的逻辑 第二,我一直试着比较x->next的计数,直到我发现一个比我想推回的大。然后我交换它们。我使用了许多指针,但有时可以工作,但在某些边缘情况下失败 我本应该保存一些代码,让人们指出我的逻辑缺陷,但我只是有点沮丧,试图从头开始 有人能提供一些好的逻辑或显式伪逻辑吗?多谢各位 #include<stdio.h> #inclu
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#define MAX 999
typedef struct Node
{
char *name;
int count;
struct Node *next;
}node;
void insert(node **,char *);
void freeNode(node **);
int main()
{
char str[MAX];
node *head = NULL;
while(getword(str,MAX))
{
insert(&head,str);
}
print(head);
free(head);
return 0;
}
void insert(node **head,char *str)
{
node *mid = *head;
node *left = NULL, *right = NULL;
while(mid)
{
if(strcmp(mid->name,str) == 0)
{
++(mid->count);
node *temp = left;
while(mid->count > right->count)
{
//printf("in %s %s %s\n",left->name,mid->name, right->name);
left->next = mid->next;
mid->next = right->next;
right->next = mid;
left = left->next;
if(mid->next != NULL) right = mid->next;
if(left == mid) break;
//printf("in %s %s %s\n\n",left->name,mid->name, right->name);
// sleep(3);
}
return;
}
left = mid;
mid = mid->next;
if(mid != NULL) right = mid->next;
}
node *newnode = (node *) malloc(sizeof(node));
newnode->name = (char *) malloc(MAX * sizeof(char));
strcpy(newnode->name,str);
newnode->count = 1;
newnode->next = *head;
*head = newnode;
}
void freeNodes(node **head)
{
node *temp;
while(*head)
{
temp = (*head)->next;
free(*head);
(*head) = NULL;
(*head) = temp;
}
}
#包括
#包括
#包括
#包括
#定义最大999
定义表结点
{
字符*名称;
整数计数;
结构节点*下一步;
}节点;
无效插入(节点**,字符*);
void freeNode(节点**);
int main()
{
字符str[MAX];
node*head=NULL;
while(getword(str,MAX))
{
插入(&head,str);
}
打印头;
自由(头);
返回0;
}
空插入(节点**头,字符*str)
{
节点*中间=*头部;
节点*left=NULL,*right=NULL;
中途(中)
{
if(strcmp(mid->name,str)==0)
{
++(中->计数);
节点*温度=左侧;
同时(中间->计数>右侧->计数)
{
//printf(“在%s%s%s\n”中,左->名称,中->名称,右->名称);
左->下一步=中->下一步;
中->下一步=右->下一步;
右->下一步=中间;
左=左->下一步;
如果(mid->next!=NULL)right=mid->next;
如果(左=中)断开;
//printf(“在%s%s%s\n\n”中,左->名称,中->名称,右->名称);
//睡眠(3);
}
返回;
}
左=中;
mid=mid->next;
如果(mid!=NULL)right=mid->next;
}
node*newnode=(node*)malloc(sizeof(node));
newnode->name=(char*)malloc(MAX*sizeof(char));
strcpy(newnode->name,str);
newnode->count=1;
新建节点->下一步=*头部;
*头=新节点;
}
无效自由节点(节点**头部)
{
节点*温度;
while(*头)
{
温度=(*头部)->下一步;
自由(*头);
(*头)=空;
(*水头)=温度;
}
}
我刚刚处理了几个边缘案例。我确保当第一个节点被重复时,将确保向下移动1
node *mid = *head;
node *left = NULL, *right = NULL;
while(mid)
{
if(strcmp(mid->name,str) == 0)
{
++(mid->count);
if(mid->next == NULL) return;
node *temp = left;
if(left == NULL)
{
left = mid->next;
mid->next = left->next;
left->next = mid;
*head = left;
right = mid->next;
}
while(mid->count > right->count)
{
left->next = mid->next;
mid->next = right->next;
right->next = mid;
left = left->next;
if(mid->next != NULL) right = mid->next;
if(left == mid) break;
//printf("in %s %s %s\n\n",left->name,mid->name, right->name);
// sleep(3);
}
return;
}
left = mid;
mid = mid->next;
if(mid != NULL) right = mid->next;
}
谷歌合并排序。IMHO它是对单连通列表进行排序的最佳算法 从以下节点列表开始:
node3 -> node7 -> node1 -> node20 -> node11 -> node13 -> NULL
长度为1的每个子列表(通常)排序如下:
然后将两个长度为1的连续子列表合并为长度为2的子列表:
node3 -> node7 -> node20 -> node1 -> node11 -> node13 -> node007 -> NULL
进入
node007
被认为等于node7
然后将两个长度为2的连续子列表合并为长度为4的子列表:
{node3 -> node7}->{node1 -> node20}->{node11 -> node13}->{node007} -> NULL
merge(node3, node1, 2):
returns {node1 -> node3 -> node7 ->node20}
merge(node11, node007, 2):
returns {node007 -> node11 -> node13}
{node1 -> node3 -> node7 ->node20}->{node007 -> node11 -> node13}->NULL
merge(node1,node007,4):
returns
{node1 -> node3 -> node7 -> node007 -> node11 -> node13 -> ode20}->NULL
因此,您将得到两个长度为4的已排序子列表:
{node3 -> node7}->{node1 -> node20}->{node11 -> node13}->{node007} -> NULL
merge(node3, node1, 2):
returns {node1 -> node3 -> node7 ->node20}
merge(node11, node007, 2):
returns {node007 -> node11 -> node13}
{node1 -> node3 -> node7 ->node20}->{node007 -> node11 -> node13}->NULL
merge(node1,node007,4):
returns
{node1 -> node3 -> node7 -> node007 -> node11 -> node13 -> ode20}->NULL
所以长度总是加倍,当它等于或大于整个列表的长度时,您就完成了
合并总是比较每个列表的第一个元素,从列表中弹出较小的元素,并将其附加到结果尾部:
merge(n1 = {node3 -> node7}->t1 , n2 = {node1 -> node20}-> t2 , 2):
做
count1=count2=2;
结果=空;
as node1NULL;
n2={node20}->t2;
count2=1;
作为node3node3}->NULL;
n1={node7}->t1;
count1=1;
作为node7node3->node7}->NULL;
n1=t1;
count1=0;(合并完成);
作为计数2!=0:result={node1->node3->node7->node20}->NULL。
这是所有的伪代码,应该给你一个想法。要交换“当前”节点和“当前的下一个”节点,你还需要跟踪“当前的上一个”节点。要进行(冒泡)排序,请在列表上循环,如果“current”大于“next of current”,则交换这两个节点。执行此操作直到不执行任何交换。@一些程序员朋友我试图使用左中右预电流、当前和当前->下一步,但我尝试执行当前->下一步的条件总是失败并使程序崩溃您的目的不清楚。是否要插入到有序列表中?
count1 = count2 = 2;
result = NULL;
as node1 < node3 : result = { node1 }-> NULL;
n2 = { node20 } -> t2;
count2 = 1;
as node3 < node20 : result = {node1 -> node3}-> NULL;
n1 = {node7}->t1;
count1 = 1;
as node7 < node20 : result = {node1 -> node3-> node7 }-> NULL;
n1 = t1;
count1 = 0; (merge finished);
as count2 != 0 : result = {node1 -> node3-> node7 -> node20 } -> NULL.