標籤:style blog http color io strong for art
58.從尾到頭輸出鏈表(鏈表)。
題目:輸入一個鏈表的頭結點,從尾到頭反過來輸出每個結點的值。鏈表結點定義如下:
struct ListNode
{
int m_nKey;
ListNode* m_pNext;
};
我的思路:用一個數組存起來已有的數字,再反過來輸出。缺點是數組大小是確定的 鏈表長度不能超過數組的大小
/*58.從尾到頭輸出鏈表(鏈表)。題目:輸入一個鏈表的頭結點,從尾到頭反過來輸出每個結點的值。鏈表結點定義如下:struct ListNode{int m_nKey;ListNode* m_pNext;};*/#include <stdio.h>#include <stdlib.h>typedef struct ListNode{int m_nKey;ListNode* m_pNext;}ListNode;void addNode(ListNode * &pHead, int data){ ListNode * x; x = pHead; while(x != NULL && x->m_pNext != NULL) { x = x->m_pNext; } if(x == NULL) { pHead = (ListNode *)malloc(sizeof(ListNode)); pHead->m_nKey = data; pHead->m_pNext = NULL; } else { x->m_pNext = (ListNode *)malloc(sizeof(ListNode)); x->m_pNext->m_nKey = data; x->m_pNext->m_pNext = NULL; }}void printformback(ListNode * pHead){ int * store = (int *)malloc(100 * sizeof(int)); //對輸入的鏈表長度有限制 int num = 0; ListNode * x = pHead; while(x != NULL) { store[num++] = x->m_nKey; x = x->m_pNext; } for(int i = num - 1; i >= 0; i--) { printf("%d ", store[i]); } printf("\n"); free(store);}int main(){ ListNode * a = NULL; addNode(a, 1); addNode(a, 2); addNode(a, 3); addNode(a, 4); addNode(a, 5); addNode(a, 6); addNode(a, 7); printformback(a); return 0;}
網上找答案 我果然實現的很挫... 居然沒有想到棧!
講解的網址:http://blog.csdn.net/chentaihan/article/details/6651795
三種方式實現--從尾到頭輸出鏈表
方法一:借用棧倒序輸出鏈表
方法二:先翻轉鏈表,再順序輸出
方法三:遞迴實現,一個妙,兩個字妙啊
方法一:借用棧倒序輸出鏈表
因為棧是先進後出,把鏈表中的元素存進棧中,鏈表前面的元素在棧底,後面的元素在棧頂,鏈表後面的元素先出棧
方法二:先翻轉鏈表,再按順序列印(主要是想自己實現單鏈表的翻轉,這種實現方式破壞了鏈表的結構,當然再翻轉一下就還原了)
翻轉鏈表的步驟:
1:將當前節點的next節點指向他以前的前一個節點
2:當前節點下移一位
3:如果是最後一個節點,就把它的next節點指向它以前的前一個節點,並推出迴圈
方法三:用遞迴實現
很誠實的說盜用了別人的思想,真的太妙了,完全能看出你是否真的體會了遞迴的原理
正如那位哥們所說,遞迴就是一個進棧出棧的過程,鏈表前面的元素先進棧,在棧底,後面的元素後進棧,在棧頂,先出棧,哈哈。。。
//三種方式實現--從尾到頭輸出鏈表#include <stack>using namespace std;class OutFromEnd{ public: typedef struct node1 { int data; node1* next; node1(int d):data(d),next(NULL){} } node; OutFromEnd() { head=cur=new node(-1); } void add(int data) { node* tmp=new node(data); cur->next=tmp; cur=tmp; } //借用棧倒序輸出鏈表 //因為棧是先進後出,把鏈表中的元素存進棧中,鏈表前面的元素在棧底,後面的元素在棧頂,鏈表後面的元素先出棧 void stackMethod() { if(NULL==head || NULL==head->next) { return; } node* tmp=head->next; stack<int> s; while(tmp!=NULL) { s.push(tmp->data); tmp=tmp->next; } while(!s.empty()) { cout<<s.top()<<"\t"; s.pop(); } } /* 先翻轉鏈表,再按順序列印(主要是想自己實現單鏈表的翻轉,這種實現方式破壞了鏈表的結構,當然再翻轉一下就還原了) 翻轉鏈表的步驟: 1:將當前節點的next節點指向他以前的前一個節點 2:當前節點下移一位 3:如果是最後一個節點,就把它的next節點指向它以前的前一個節點,並推出迴圈 */ void reverse() { if(NULL==head || NULL==head->next) { return; } cur=head->next; node* prev=NULL; node* pcur=head->next; node* next; while(pcur!=NULL) { if(pcur->next==NULL) { pcur->next=prev; break; } next=pcur->next; pcur->next=prev; prev=pcur; pcur=next; } head->next=pcur; node* tmp=head->next; while(tmp!=NULL) { cout<<tmp->data<<"\t"; tmp=tmp->next; } } void print3() { recursion(head->next); } //用遞迴實現 //很誠實的說盜用了別人的思想,真的太妙了,完全能看出你是否真的體會了遞迴的原理 //正如那位哥們所說,遞迴就是一個進棧出棧的過程,鏈表前面的元素先進棧,在棧底,後面的元素後進棧,在棧頂,先出棧,哈哈。。。 void recursion(node* head) { if(NULL==head) { return; } if(head->next!=NULL) { recursion(head->next); } //如果把這句放在第二個if前面,那就是從頭到尾輸出鏈表,曾經的你或許是用while或者用for迴圈輸出鏈表,現在你又多了一種方式 cout<<head->data<<"\t"; } private : node *head,*cur;};