1. 程式人生 > 其它 >新增連結串列節點、連結串列的倒序查詢、列印

新增連結串列節點、連結串列的倒序查詢、列印

1.其實用的是快慢指標,來倒查某個元素。

#include<iostream>
#include<stdlib.h>
#include<stack>
 
using namespace std;
  
typedef int USER_TYPE;//連結串列中資料使用者可以只在這裡修改就可以完成
 
//連結串列結構
struct ListNode
{
	USER_TYPE data;
	ListNode* pNext;
};
 
 
typedef struct ListNode ListNode;
 
//建立一個連結串列結點
ListNode* createListNode(int value)
{
	ListNode *pNode = new ListNode();
	pNode->data = value;
	pNode->pNext = NULL;  
	return pNode; 
} 
 
//遍歷連結串列中的所有結點
void printList(ListNode* pHead)
{
	ListNode *pNode = pHead;
	while (pNode != NULL)
	{
		cout << pNode->data << " ";
		pNode = pNode->pNext;
	}
	cout << endl;
} 
 
//輸出連結串列中的某一結點的值
void printListNode(ListNode* pNode)
{
	if (pNode == NULL)
	{
		printf("The node is NULL\n");
	}
	else
	{
		printf("The key in node is %d.\n", pNode->data);
	}
}
 
//往連結串列末尾新增結點
/*
注意這裡pHead是一個指向指標的指標,在主函式中一般傳遞的是引用。
因為如果要為連結串列新增結點,那麼就會修改連結串列結構,所以必須傳遞引用才能夠儲存修改後的結構。
*/
void addToTail(ListNode** pHead, int value)
{
	ListNode* pNew = new ListNode();//新插入的結點
	pNew->data = value;
	pNew->pNext = NULL;
 
 
	if (*pHead == NULL)//空連結串列
	{
		*pHead = pNew;
	}
	else
	{
		ListNode* pNode = *pHead;
		while (pNode->pNext != NULL)
			pNode = pNode->pNext;
		pNode->pNext = pNew;
	}
}
 

//對空指標等輸入進行判斷,魯棒性更好
ListNode* findKthNodeFromEnd2(ListNode* pHead, int k)
{
	if (pHead == NULL || k == 0) //判斷指標為空 k == 0的情況;
		return NULL;
 
	ListNode* pNode = pHead;//當前結點
	ListNode* pKthNode = pHead;//
 
	while (k - 1 > 0)
	{
		if (pNode->pNext != NULL) //判斷 k-1<0的情況
		{
			pNode = pNode->pNext;//讓pNode先走k-1步,快慢指標
			--k;
		}
		else
			return NULL;
	} 
	while (pNode->pNext != NULL)
	{
		pNode = pNode->pNext;
		pKthNode = pKthNode->pNext;
	} 
	return pKthNode;
}
 
void main()
{
	//建立結點
	ListNode* pNode1 = createListNode(1);//建立一個結點
	printList(pNode1);//列印
	//往連結串列中新增新結點
	addToTail(&pNode1, 22);//為連結串列新增一個結點,傳入地址用於指標間接修改node之和list
	addToTail(&pNode1, 33);//為連結串列新增一個結點
	addToTail(&pNode1, 44);//為連結串列新增一個結點
	addToTail(&pNode1, 55);//為連結串列新增一個結點
	addToTail(&pNode1, 66);//為連結串列新增一個結點
	addToTail(&pNode1, 77);//為連結串列新增一個結點
	//列印連結串列
	printList(pNode1);//列印
	//返回第二個指標指向的加點,該節點就是倒數第k個數字
	ListNode* KthNode = findKthNodeFromEnd2(pNode1, 2); 
	printListNode(KthNode);
	system("pause");
 
}

2.單鏈表逆序的四種思路(陣列,棧,逆序連結串列,遞迴)

/*************************************************************************
> Function: 連結串列逆序的四種思路(陣列,棧,逆序連結串列,遞迴)
 ************************************************************************/
#include <iostream>
#include <vector>
#include <stack>
#include <stdlib.h>
#include <time.h>

using namespace std;

struct Node
{
    int data;
    Node *next;
};

//寫一個連結串列類,實現四種連結串列逆序列印方式(陣列,棧,逆序連結串列,遞迴)
class LinkList
{
public:
    LinkList(){head = new(Node);head->next = NULL;}
    void setRandList(int len); //生成len個隨機數並插入連結串列
    void insert(int i,int index = 1); //插入,可指定位置,預設頭插
    void print() const; //列印
    void invertPrint_vector() const;//使用陣列,不改變連結串列本身
    void invertPrint_stack() const;//使用棧,不改變連結串列本身
    void invertprint_linklist();//直接逆序連結串列
    void invertprint_recursion() const;//遞迴列印,不改變連結串列本身
    void invertprint_recursion(Node * node) const; //遞迴時需傳參呼叫該函式

private:
    Node * head;
    int length = 0;
};

void LinkList::setRandList(int len)
{
    srand((unsigned)time(NULL));
    for(int i = 0;i < len; i++)
    {
        insert(rand()%99+1);
    }
}

void LinkList::insert(int data,int index)
{
    if(index > length + 1)
    {
        throw "位置出錯!";
    }
    else
    {
        Node *p = head;
        for(int i = 1; i < index; i++)
        {
            p = p->next;
        }
        Node *newnode = new Node;
        newnode->data = data;
        newnode->next = p->next;
        p->next = newnode;
        length++; 
    }
}

void LinkList::print() const
{
    if(NULL == head->next){return;}
    cout << "\n當前正序輸出:";
    Node *p = head->next;
    while(NULL != p)
    {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

void LinkList::invertPrint_vector() const
{
    if(NULL == head->next){return;}
    cout << "陣列倒序:";
    vector<int> v;
    Node *p = head->next;
    while(NULL != p)
    {
        v.emplace_back(p->data);
        p = p->next;
    }
    for(auto it = v.end() - 1; it >= v.begin(); it--)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void LinkList::invertPrint_stack() const
{
    if(NULL == head->next){return;}
    cout << "棧 倒 序:";
    stack<int> s;
    Node *p = head->next;
    while(NULL != p)
    {
        s.push(p->data);
        p = p->next;
    }
    while(!s.empty())
    {
        cout << s.top() << " ";
        s.pop();
    }
    cout << endl;
}

void LinkList::invertprint_linklist()
{
    if(NULL == head->next){return;}
    cout << "逆序連結串列(此處使用方法執行過程不列印):\n";
    Node *p = new(Node);
    p->next = head->next;
    Node *q = new(Node);
    q->next = p->next->next;
    head->next->next = NULL;//必須置空,否則尾節點自迴圈列印會出錯
    head->next = q->next->next;   
    for(int i = 1; i < length - 2; i++)
    {
        q->next->next = p->next;
        p->next = q->next;
        q->next = head->next;
        head->next = head->next->next;
    }
    q->next->next = p->next;
    head->next->next = q->next;
    delete p;
    delete q;
}

void LinkList::invertprint_recursion() const
{  
    if(NULL == head->next){return;}
    cout << "遞迴倒序:";
    invertprint_recursion(head); 
    //本笨蛋目前沒想到更好的用一個函式解決該遞迴的方法,預設引數為head會報錯。
    //如有大佬,請教我!
    cout << endl;
}

void LinkList::invertprint_recursion(Node * node) const
{
    if(NULL == node->next)
    {
        return;
    }    
    invertprint_recursion(node->next);
    cout << node->next->data << " ";  
    //在這裡要說明的是,如果把列印放在遞迴呼叫前,可以實現正序列印連結串列
}

int main()
{
    LinkList ll;
    ll.setRandList(10);
    ll.print();
    ll.invertPrint_vector();

    ll.print();
    ll.invertPrint_stack();
    
    ll.print();
    ll.invertprint_linklist1();
    
    ll.print();
    ll.invertprint_recursion();

    ll.print();
    ll.invertprint_recursion();

    ll.print();

    return 0;
}

轉載:https://blog.csdn.net/qq_54676460/article/details/119832471