簡單的演算法(1)--從尾到頭列印連結串列
阿新 • • 發佈:2018-11-28
目錄
1、java實現
連結串列的定義:
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
1.1、遞迴
public class Solution { ArrayList<Integer> arrayList=new ArrayList<Integer>(); public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { if(listNode!=null){ this.printListFromTailToHead(listNode.next); arrayList.add(listNode.val); } return arrayList; } }
此方式雖然看起來簡潔,如果連結串列很長時,就會導致函式的呼叫層級很深,有可能會導致函式棧溢位。
1.1.1、測試(完整原始碼)
import java.util.ArrayList; /** * @Auther: zj * @Date: 2018/11/6 17:18 * @Description: 從尾到頭列印連結串列 */ public class t7 { //測試 public static void main(String[] args) { ListNode listNode = new ListNode( 1 ); listNode.next = new ListNode( 3 ); listNode.next.next = new ListNode( 5 ); ListNode head=listNode; while (head!=null){ System.out.print( head.val+"->" ); head=head.next; } System.out.print( "\n" ); Solution s= new Solution(); System.out.println( s.printListFromTailToHead( listNode ) ); } } //定義連結串列 class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } //從尾到頭列印連結串列 class Solution { ArrayList<Integer> arrayList=new ArrayList<Integer>(); ArrayList<Integer> printListFromTailToHead(ListNode listNode) { if(listNode!=null){ this.printListFromTailToHead(listNode.next); arrayList.add(listNode.val); } return arrayList; } }
1.2、利用棧來實現
//法2:利用棧來
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
Stack<Integer> stack = new Stack<Integer>();
while(listNode!=null) {
stack.push(listNode.val);
listNode=listNode.next;
}
ArrayList<Integer> arrayList = new ArrayList<Integer>();
while(!stack.isEmpty()){
arrayList.add(stack.pop());
}
return arrayList;
}
1.2.1、測試
import java.util.ArrayList;
import java.util.Stack;
/**
* @Auther: zj
* @Date: 2018/11/6 17:18
* @Description: 從尾到頭列印連結串列
*/
public class t7 {
public static void main(String[] args) {
ListNode listNode = new ListNode( 1 );
listNode.next = new ListNode( 3 );
listNode.next.next = new ListNode( 5 );
ListNode head=listNode;
while (head!=null){
System.out.print( head.val+"->" );
head=head.next;
}
System.out.print( "\n" );
Solution s= new Solution();
System.out.println( s.printListFromTailToHead( listNode ) );
}
}
//定義連結串列
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
//法2:利用棧來
class Solution {
ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
Stack<Integer> stack = new Stack<Integer>();
while(listNode!=null) {
stack.push(listNode.val);
listNode=listNode.next;
}
ArrayList<Integer> arrayList = new ArrayList<Integer>();
while(!stack.isEmpty()){
arrayList.add(stack.pop());
}
return arrayList;
}
}
2、C語言
與java類似
2.1、先將連結串列反轉,再從頭輸出(改變連結串列的結構)
從頭到尾輸出比較簡單,於是我們很自然地想到把連結串列中連結結點的指標反轉過來,改變連結串列的方向,就可以從頭到尾輸出了。
#include<stdio.h>
#include<stdlib.h>
//連結串列的相關操作
//定義連結串列的結構
typedef struct LNode *PtrToLNode;
struct LNode {
int data;//資料域,用於儲存資料
PtrToLNode Next;//指標,可以用來訪問節點資料,也可以遍歷,指向下一個節點
};
//初始化
PtrToLNode init(int n) {
PtrToLNode head,node,end;//定義頭節點,普通節點,尾部節點;
head = (PtrToLNode)malloc(sizeof(struct LNode));
scanf("%d",&(head->data));//頭指標賦值
end =head;
for(int i=0;i<n;i++) {//新增結點
node = (PtrToLNode)malloc(sizeof(struct LNode));
scanf("%d",&(node->data));
end->Next=node;
end=node;
}
end->Next = NULL;//結束建立
return head;
}
//反轉單鏈表
PtrToLNode reverseLNode(PtrToLNode head) {
if(head==NULL||head->Next==NULL) //少於兩個節點沒有反轉的必要
return head;
PtrToLNode p,q,r;
p= head;
q=head->Next;
head->Next=NULL;//舊的頭指標是新的尾指標,next需要指向NULL
while(q) {
r=q->Next; //先保留下一個step要處理的指標
q->Next=p;//然後p q交替工作進行反向
p=q;
q=r;
}
head=p;// 最後q必然指向NULL,所以返回了p作為新的頭指標
return head;
}
int main(void) {
int n=3;
PtrToLNode head = init(n);//連結串列初始化&&連結串列賦值
PtrToLNode node=head;
while(node!=NULL) {
printf("%d->",node->data);//列印連結串列
node = node->Next;
}
printf("\n反轉連結串列:\n");
PtrToLNode end =reverseLNode(head);//反轉連結串列
while(end!=NULL) {
printf("%d->",end->data);
end=end->Next;
}
return 0;
}
2.2、利用棧的“先進後出”特性
#include<stdio.h>
#include<stdlib.h>
//連結串列的相關操作
//定義連結串列的結構
typedef struct LNode *PtrToLNode;
struct LNode {
int data;//資料域,用於儲存資料
PtrToLNode Next;//指標,可以用來訪問節點資料,也可以遍歷,指向下一個節點
};
//定義棧的結構
typedef struct StackNode *PtrToStack;
struct StackNode {
int data;
PtrToStack Next;
};
//連結串列初始化及賦值
PtrToLNode init(int n) {
PtrToLNode head,node,end;//定義頭節點,普通節點,尾部節點;
head = (PtrToLNode)malloc(sizeof(struct LNode));
scanf("%d",&(head->data));//頭指標賦值
end =head;
for(int i=0;i<n;i++) {//新增結點
node = (PtrToLNode)malloc(sizeof(struct LNode));
scanf("%d",&(node->data));
end->Next=node;
end=node;
}
end->Next = NULL;//結束建立
return head;
}
//棧的初始化
PtrToStack createStack() {
PtrToStack head;
head = (PtrToStack)malloc(sizeof(struct StackNode));
head->Next=NULL;
return head;
}
//判斷棧是否為空
int IsEmpty(PtrToStack s) {
if(s->Next==NULL) {
return 1;
} else {
return 0;
}
}
//壓棧
void Push(PtrToStack s,int X) {
PtrToStack tmp = (PtrToStack)malloc(sizeof(struct StackNode));
tmp->data=X;
tmp->Next=s->Next;
s->Next=tmp;
}
//出棧
int Pop(PtrToStack s) {//棧頂
PtrToStack FirstCell;
int tmp;
if(IsEmpty(s)) {
printf("該堆疊為空");
return -1;
} else {
FirstCell = s->Next;
tmp = FirstCell->data;
s->Next=FirstCell->Next;
free(FirstCell);
}
return tmp;
}
int main(void) {
int n=3;
PtrToLNode head = init(n);//連結串列初始化&&連結串列賦值
PtrToLNode node=head;
while(node!=NULL) {
printf("%d->",node->data);//列印連結串列
node = node->Next;
}
printf("\n利用棧反向輸出連結串列:\n");
PtrToStack stack_head=createStack();
PtrToLNode bbb=head;
while(bbb!=NULL) {
printf("%d\n",bbb->data);
Push(stack_head,bbb->data);//入棧
bbb = bbb->Next;
}
PtrToStack stack_bbb=stack_head;
printf("\n列印棧:\n");
PtrToStack ccc=stack_head->Next;//剔除棧頂元素
while(ccc!=NULL) {
printf("%d->",ccc->data);
ccc = ccc->Next;
}
return 0;
}
非常簡單的題目,就是容易錯:p