單鏈表演算法
① 數據結構關於單鏈表演算法問題
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。因此必須採取指針參數傳遞的辦法,否則無法在被調函數中修改主函數中定義的變數的內容。以下的代碼也有類似的情況。