单链表算法
① 数据结构关于单链表算法问题
typedef
int
ElemType;
typedef
struct
LNode
/*定义链表结点类型*/
{
ElemType
data;
struct
LNode
*
next;
}LNode,
*
LinkList;
void
Output_des(LinkList
*head)
{//按值递减的次序逐个输出head中各结点的数据元素,同时释放该结点空间。利用简单的插入排序思想。
LNode
*q,*pre_q,*p,*pre_p;//q指向元素值最大的结点,pre_q指向q结点的前驱结点,pre_p指向p所指结点的前驱
while((*head)->next!=NULL)
{//单链表不空,输出表中元素
q=(*head)->next
;//初始化q指向第一个结点
pre_q=(*head);//pre_q指向q的前驱即头结点
p=q->next
;//p指向q的后继结点
pre_p=q;
while(p!=NULL)
{//找出链表中值最大的结点
if(p->data>q->data)
{//如果p所指结点的元素值大于q所指结点的元素值,那么将q指向p所指的结点,同时移动pre_q
pre_q=pre_p;
q=p;
}
pre_p=p;
p=p->next;//p和pre_p移动到下一个结点
}
printf("%d\t",q->data);//输出元素值
pre_q->next=q->next;//删除最大的结点q
free(q);//释放该结点
}
free(*head);//释放头结点
}
② 数据结构 单链表初始化算法
这个是创建单链表表头的一个函数:
LinkList
CreatNullListlink(void)
//
函数名,不带参数,返回链表头head(LinkList
类型)
{
LinkList
head;//定义一个链表,
head=(LinkList)malloc(sizeof(listnode));
//给这个链表分配内存控件
head->next=Null;//初始化只有链表头,头链表所指向的下一个链表为空
return(head);//返回这个头链表
}
这个函数只是初始化链表的一个头链表,头链表指向的下一个链表为空。
现在是:
头链表----->X(NULL)
下一步就是要向头链表里添加值。
头链表------>下一个链表------>下一个链表------->下一个链表----->..........------>尾链表.
这些是数据结构的基本只是,为编程打基础的,只有基础打好了,以后发展很有帮助。祝你好运,加油哦!
③ 数据结构单链表设计算法
从头位置值开始依次与下一节点值比较取小值并记录小的节点位置。
SLink* t,t_pos;
t = head;
if(t->data > t->next->data)
{
t_pos = t->next;
}else
{
t_pos =t;
}
t = t->next;
④ 请教关于尾插法建立单链表的算法
tailing是通过在列表尾部逐个插入新节点来创建列表。与前面的插值一样,每次应用新节点时,都会读入相应的数据元素值。不同之处在于,为了将新节点插入表的尾部,需要添加尾部指针r来指向链表的尾部。
[算法步骤]
创建一个只有头节点的空链表。
②尾部指针R的初始化,指向头部节点。
③根据链表创建中包含的元素n的个数,进行n个循环的以下操作:
生成新节点*p;
●将输入元素值赋给新节点*p的数据字段;
●在尾节点*R后插入新节点*P;
●尾部指针R指向新尾部节点*PS
如图所示,线性表(A、B、C、D、E)后插值的创建过程与线性表相同。
【算法描述】
voidCreatelist_R(Linklist&L,intn) //正位序输入n个元素的值,建立带表头结点的单链表L个人
{
L=newLNode; //先建立一个带头结点的空链表L->next=NULL; //尾指针指向头结点r=L;
for(i=0;i<n:++i) //生成新
{
p=newLNode; //输入元素值赋给新结点p的数据域cin>>p->data; //将新*p插入尾结点*r之后p->next=NULL;r->next=p;
r=p; //r指向新的尾结点*p
}
}
算法时间复杂度为O(n)。
(4)单链表算法扩展阅读:
尾部插入方法从空表开始,重复读取数据,生成新节点,将读取的数据存储在新节点的数据字段中,然后将新节点插入到当前链表的尾部,直到读取标记结束。从空表开始,重复读取数据,生成新节点,将读取的数据存储在新节点的数据字段中,然后将新节点插入到当前链表的末尾,直到读取标志结束。
⑤ 如何创建单链表
建立单链表的常用方法有两种:头插法建表、尾插法建表
⑥ 单链表的排序算法,哪位大师麻烦您说一哈,感激不尽!
这个比较恶心,最好使用插入排序的方式,效率稍微高点。先对数组排序实现一个插入排序,代码不多,可以写一个。然后就按照那种思想,将链表节点拿出来插入到正确位置。
后来是刷题刷到的一个题目吧,好像是使用快慢指针的方式,采用归并排序,性能算nlgn吧。这个算法分为以下三步,
利用快慢指针找到链表的中间节点,O(n/2)
分别执行n/2长度的归并算法,2*T(n/2)
对两段归并的结果进行merge,O(n)
T(n) = O(n/2) + 2*T(n/2) + O(n)
上面的这个公式的时间复杂度是O(n*lgn)
⑦ C语言单链表算法问题
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
void InitList(LinkList *L);
void ListDeleteMax(LinkList L,int *e);
int ListInsert(LinkList L,int i,int e);
void DestroyList(LinkList L);
void ListTraverse(LinkList L);
int main(void)
{
LinkList L;
int i,j,m;
int a[]={6,5,4,3,2,1};
InitList(&L);
for(i=0; i<6; ++i)
m = ListInsert(L,i+1,a[i]);
printf("链表的内容为:");
ListTraverse(L);
ListDeleteMax(L,&j);
printf("删除最大元素%d后,链表的内容为:",j);
ListTraverse(L);
DestroyList(L);
return 0;
}
void InitList(LinkList *L)
{
*L = (LinkList )malloc(sizeof(LNode));
if(!*L)
exit(-1);
(*L)->next = NULL;
}
int ListInsert(LinkList L,int i,int e)
{
int j=0;
LinkList p = L;
LinkList s;
while(p&&j<i-1)
{
p = p->next;
j++;
}
if(!p || j>i-1)
{
return 0;
}
s = (LinkList)malloc(sizeof(LNode));
s ->data = e;
s->next = p->next;
p->next = s;
return 1;
}
void ListDeleteMax(LinkList L,int *e) //删除最大元素
{
LinkList p = L->next;
LinkList s = L; //s指向最大结点前面的结点
LinkList q;
int m = p->data; //m保存最大的值
while(p->next)
{
q=p->next;
if(q->data > m)
{
m = q->data;
s = p;
}
p=p->next;
}
q = s->next;
s->next = q->next;
*e = q->data;
free(q);
}
void DestroyList(LinkList L)
{
LinkList q;
while(L)
{
q = L->next;
free(L);
L = q;
}
}
void ListTraverse(LinkList L)
{
LinkList p = L->next;
while(p)
{
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
⑧ 数据结构 单链表 算法
#include<stdio.h>
// 对于节点的定义
struct Node
{
int data;
struct Node *next;
};
// 合并两个递减有序的链表
struct Node *merge(struct Node *p1, struct Node *p2)
{
struct Node *head = NULL, *p = NULL, *pt;
// 当两链表均不空时的合并逻辑
while(p1 && p2)
{
// 将两链表当前节点中值较大的一个记录下来,
// 并后移指向该链表当前节点的指针
if(p1->data > p2->data)
{
pt = p1;
p1 = p1->next;
}
else
{
pt = p2;
p2 = p2->next;
}
if(p == NULL)
{
// 若当前新链表为空,将p和head指向找到的节点
head = p = pt;
}
else
{
// 将新节点链入当前链表尾部
p->next = pt;
p = pt;
}
}
// 找到隶完成合并的那个链表,将其链接到新链表的尾部
pt = p1 == NULL ? p2 : p1;
if(pt)
{
if(p == NULL)
{
// 如果新链表仍为空,直接指向非空的链表
head = p = pt;
}
else
{
// 将未完成合并的链表链接到新链表的尾部
p->next = pt;
}
}
return head;
}
// 链表倒置
struct Node *reverse(struct Node *head)
{
struct Node *newHead = NULL, *p;
if(!head)
{
return newHead;
}
// 先将新的头指针指向原链表的第一个节点
newHead = head;
head = head->next;
newHead->next = NULL;
// 将原链表中剩下的节点依次加到新链表的头部,以实现倒序
while(head)
{
p = head->next;
head->next = newHead;
newHead = head;
head = p;
}
return newHead;
}
int main()
{
struct Node *h1, *h2, *head;
// 生成原始的两个链表的逻辑请自行编写
// 首先,合并两个链表
head = merge(h1, h2);
// 然后,将合并后的链表倒置
head = reverse(head);
// 输出处理后的链表中的内容
while(head)
{
printf("%d ", head->data);
head = head->next;
}
getchar();
return 0;
}
以上程序是按照 zhangchaoyiay 所说的算法思路编写,其实在合并的过程中,可以直接完成倒序操作,这个楼主自己琢磨一下好了,呵呵
⑨ 从表头插入节点建立单链表的算法如何写
何在指针q指向的结点后面插入结点。该过程的步骤如下:
(1)先创建一个新结点,并用指针p指向该结点。
(2)将q指向的结点的next域的值(即q的后继结点的指针)赋值给p指向结点的next域。
(3)将p的值赋值给q的next域。
通过以上3步就可以实现在链表中由指针q指向的结点后面插入p所指向的结点。可以通过图1-5形象地展示出这一过程。
图1-5
向链表插入结点过程
下面给出代码描述:
1.void
insertList(LinkList
*list,LinkList
q,ElemType
e)
/*当链表为空时*/
10.
else
16.}
上面的这段代码描述了如何在指针q指向的结点后面插入结点的过程。其过程包括以下几步。
(1)首先生成一个新的结点,大小为sizeof(LNode),用LinkList类型的变量p指向该结点。将该结点的数据域赋值为e。
(2)接下来判断链表是否为空。如果链表为空,则将p赋值给list,p的next域的值置为空。否则,将q指向的结点的next域的值赋值给p指向结点的next域,这样p指向的结点就与q指向结点的下一个结点连接到了一起。
(3)然后再将p的值赋值给q所指结点的next域,这样就将p指向的结点插入到了指针q指向结点的后面。
其实通过上面这段算法描述可以看出,应用这个算法同样可以创建一个链表。这是因为当最开始时链表为空,即list==NULL,该算法可自动为链表创建一个结点。在下面的创建其他结点的过程中,只要始终将指针q指向链表的最后一个结点,就可以创建出一个
链表。
注意:函数insertList()的参数中有一个LinkList
*list,它是指向LinkList类型的指针变量,相当于指向LNode类型的指针的指针。这是因为在函数中要对list,也就是表头指针进行修改,而调用该函数时,实参是&list,而不是list。因此必须采取指针参数传递的办法,否则无法在被调函数中修改主函数中定义的变量的内容。以下的代码也有类似的情况。