c++ 建立有序單鏈表,以及兩個有序單鏈表合併
阿新 • • 發佈:2018-12-30
首先是Node結點的建立
//建立結點
class Node
{
public:
Node(){
next=NULL;data=0;
}
Node(int n){
next=NULL;data=n;
}
int data;
Node *next;
};
這道題需要三個函式實現相應功能
列印
void show(Node* first)
{
Node *p;
p=first->next;
while(p!=NULL)
{
cout<< p->data<<" ";
p=p->next;
}
cout<<endl;
}
建立有序表
void build(Node *front,int size)
{
Node *curr,*pre,*p;
cout<<"please input the data: "<<endl;
for(int i=0;i<size;i++)
{
int data;
curr=front->next;
//輸入要插入的數字
cin>>data;
//建立新結點
p=new Node(data);
//pre永遠在curr的前面,curr是每次遍歷的開始
pre=front;
//當前的結點,數字不大於插入目標時,將目標插在這個結點的前面
while(curr!=NULL&&curr->data<=data)
{
pre=curr;
curr=curr->next;
}
p-> next=curr;
pre->next=p;
}
//列印這個建立的有序表
show(front);
}
將兩個有序表合併為一個有序單鏈表
void combine(Node* f1,Node* f2,Node *f3,int n,int m)
{
//建立作為標記的結點,p指向有序表f1,q指向有序表f2,back指向新表f3
Node*p,*q,*back;
p=f1->next;
q=f2->next;
back=f3->next;
//如果兩個有序表滿足,一空一不空,則直接列印不空的那個
if (f1->next == NULL && f2->next != NULL)
{
cout<<"after combine:"<<endl;
show(f2);
}
else if(f2->next == NULL && f1->next != NULL)
{
cout<<"after combine:"<<endl;
show(f1);
}
//如果兩有序表都空,輸出blank
else if(f1->next==NULL && f2->next==NULL) cout<<"blank"<<endl;
//兩有序表均非空
else
{
//比較兩個有序表中的數字,先插小的,指標前進,繼續比較取小的
int t=0;
while(t<m+n)
{
while(p!=NULL && (q==NULL || p->data<=q->data))
{
Node *k=new Node(p->data);
//問題:原來的寫法因為k是建立的孤立結點,沒有連上就用back指去
//會造成back也脫離f3
//back=k;
//back=k->next;
//修改成如下,當f3空時,k就是第一個結點了,此後f3非空,將k插入到表尾
if(f3->next!=NULL)
back->next=k;
else
f3->next=k;
back=k;
p=p->next;
t++;
}
while(q!=NULL && (p==NULL || p->data>=q->data))
{
Node *k=new Node(q->data);
//原理同上一條註釋
//back=k;
//back=k->next;
if(f2->next!=NULL)
back->next=k;
else
f2->next=k;
back=k;
q=q->next;
t++;
}
}
cout<<endl<<"after combine:"<<endl;
//打印合並得到的有序表f3
show(f3);
}
}
其實思路很容易有,編兩個數字連結串列畫畫就能想明白,兩個有序表,頭節點為 f1和f2,用 p 標記 f1->next ,用 q 標記 f2->next ,建立一個節點 f3,它就是新連結串列的頭節點,用 back 指向它,注意這裡的 f1,f2,f3 ,都是其指向的next的指向為空,而不是它們為空,它們是有指向的。
然後就是比較大小的問題,當兩個有序表,一空一不空,則直接列印不空的那個,重點是都非空的兩個。
最外面一個while循壞,當插入次數不大於兩個表的元素數量,裡面兩個while迴圈
while(p!=NULL && (q==NULL || p->data<=q->data))
while(q!=NULL && (p==NULL || p->data>=q->data))
三個點:
1. p!=NULL 和 q!=NULL,如果沒有這兩個條件就會兩個while跳來跳去
2. q==NULL 在 || 的前面一個,因為執行順序,當為NULL時直接跳出這個while,如果是p->data<=q->data在 || 的前面,那q為NULL時就會報錯,所以先判斷
3. 兩個符號 <=、>=而不是<、>,有了這個等號避免不必要的在兩個while裡跳來跳去,相等時執行當前while裡的語句
ps:可能路過的大佬會有更簡單快速的方法,敬請賜教~