前言:數(shù)據結構屬于C++學習中較難的一部分,對應學習者的要求較高,如基礎不扎實,建議著重學習C語言中的指針和結構體,萬丈高樓平地起。
目錄:
?
一,鏈表
1)單鏈表的大致結構實現(xiàn)
2)單鏈表的思考(然后找到鏈表和判斷鏈表的結束)
3)單鏈表的程序實現(xiàn)及源代碼講解
1)鏈表的實現(xiàn)前提準備
2)單鏈表的創(chuàng)建及初始化
3)單鏈表的尾插
4)單鏈表的頭插
5)單鏈表的頭刪
6)單鏈表的尾刪
7)在單鏈表中查找元素
8)單鏈表指定結點的后面插入和刪除元素
9)單鏈表的內存銷毀
2)帶頭雙向循環(huán)鏈表的提示(自己實現(xiàn))
二,隊列和棧
1)隊列特性
2)棧的特性
3)隊列用鏈表實現(xiàn)(源代碼及詳細講解)
1)隊列結構和功能實現(xiàn)前準備
2)初始化隊列
3)入列數(shù)據
4)出列數(shù)據
5)獲取隊列頭部元素?
6)獲取隊列尾部元素
7)銷毀隊列元素
4)棧的代碼實現(xiàn)(提供另外一種思路,自己實現(xiàn))
?
一,鏈表
1)單鏈表的大致結構實現(xiàn)
用C語言實現(xiàn)鏈表一般是使用結構體,首先我們可以通過鏈表的結構特性反推結構體的成員。單鏈表是只能通過前一個節(jié)點找到下一個節(jié)點,并且是單向的,每一個節(jié)點還要存儲數(shù)據元素,我們實現(xiàn)這個的手段是指針,因此我們需要在前一個結點存儲下一個地址。
typedef int SLTDateType;//方便以后修改鏈表類型
typedef struct STLListNode {
SLTDateType n;
struct STLListNode* next;
}SListNode;//減少代碼的冗余
2)單鏈表的思考(然后找到鏈表和判斷鏈表的結束)
首先是如何找到鏈表的第一個元素,每次,我們之前的圖上給了提示,我們可以用一個head指針來標記第一個結點,但有一個很大的注意事項,我們不能隨便改變head的地址,不然我們將會無法找到這個鏈表。
那如何判斷鏈表的結束呢,看上面的手繪圖,最后一個結點所指向的是NULL指針,根據這個特點我們就可以判斷鏈表的結束。
注:我們?yōu)槭裁匆紤]這兩個問題是因為如果我們不嚴格的控制指針的指向,當指針指向為開辟的空間,會導致程序出現(xiàn)各種意外甚至無法運行。
3)單鏈表的程序實現(xiàn)及源代碼講解
1)鏈表的實現(xiàn)前提準備
#include<stdio.h>
#include<assert.h>
typedef int SLTDateType;//方便以后修改鏈表類型
typedef struct STLListNode {
SLTDateType n;
struct STLListNode* next;
}SListNode;//減少代碼的冗余
2)單鏈表的創(chuàng)建及初始化
SListNode* BuySListNode(SLTDateType x);
SListNode* BuySListNode(SLTDateType x) {
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));//分配內存空間
assert(newnode);//防止分配失敗導致的訪問非法空間
newnode->n= x;
return newnode;//返回創(chuàng)建空間地址
}
3)單鏈表的尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
void SListPushBack(SListNode** pplist, SLTDateType x) {//鏈表要傳地址用二級指針接受,因為頭插的時候是要改變鏈表的地址,是需要二級指針才能改變一級指針
SListNode* ptemp = *pplist;
SListNode** plist = pplist;//防止頭指針丟失
if (*plist == NULL) {
*plist = BuySListNode(x);
(*plist)->next = NULL;
return;
}//如果是空鏈表需要單獨處理
while ((*plist)->next != NULL) {
*plist = (*plist)->next;
}//找到尾節(jié)點
(*plist)->next = BuySListNode(x);//分配一個新空間
(*plist)->next->next = NULL;//置空方便下次找尾結點
*pplist = ptemp;//維持頭指針
}
4)單鏈表的頭插
void SListPushFront(SListNode** pplist, SLTDateType x) {//要改變頭指針的地址,需要二級指針
if (*pplist == NULL) {
*pplist = BuySListNode(x);
(*pplist)->next = NULL;
return;//如果鏈表為空,單獨處理
}
SListNode* plist= BuySListNode(x);//分配空間
plist->next = (*pplist);//將新結點的next指針指向原來的頭指針
*pplist = plist;//改變頭指針
}
5)單鏈表的頭刪
void SListPopFront(SListNode** pplist){
assert(*pplist);//判斷是否為空鏈表,防止訪問非法空間
SListNode* plist = *pplist;
*pplist = (*pplist)->next;//保留新頭
plist->next = NULL;//老的頭指針置空,防止通過這個非法訪問
free(plist);//釋放老頭指針空間
}
6)單鏈表的尾刪
void SListPopBack(SListNode** pplist) {
assert(*pplist);//判斷是否為空鏈表,防止訪問非法空間
SListNode* plist = (*pplist);//保存頭指針,防止丟失
if (plist->next == NULL) {
free(plist);
plist = NULL;
}//如果只有一個元素,直接釋放
while (plist->next->next != NULL) {
plist = plist->next;
}//找到尾結點
free(plist->next);
plist->next = NULL;//置空
}
7)在單鏈表中查找元素
SListNode* SListFind(SListNode* plist, SLTDateType x) {
assert(plist);//判斷是否為空鏈表,防止訪問非法空間
while (plist->next != NULL) {
if (plist->n = x)
return plist;//如果找到直接返回地址
plist = plist->next;//否則下一個
}
return NULL;//找到了尾結點都沒找到,返回空指針
}
8)單鏈表指定結點的后面插入和刪除元素
void SListInsertAfter(SListNode* pos, SLTDateType x) {
assert(pos);//判斷是否為空鏈表,防止訪問非法空間
SListNode* temp = pos->next;
pos->next = BuySListNode(x);
pos->next->next = temp;
}
void SListEraseAfter(SListNode* pos) {
assert(pos);//判斷是否為空鏈表,防止訪問非法空間
assert(pos->next );//判斷是否有下一個元素
SListNode* temp = pos->next;
pos->next = pos->next->next;//改變前一個指針的next指針,防止斷層
free(temp);
}
9)單鏈表的內存銷毀
void SListDestroy(SListNode* plist) {
assert(plist);//防止多次釋放空間
SListNode* cur = plist->next;//記錄當前指針,因為當前指針釋放后無法訪問到下一個指針的地址
while (cur) {
free(plist);
plist = cur;
cur = plist->next;
}
plist = NULL;
}
2)帶頭雙向循環(huán)鏈表的提示(自己實現(xiàn))
與單鏈表相比,帶頭雙向循環(huán)鏈表,會有多開辟一個空間,不用來存儲數(shù)據,用來指向head指針,這樣可以簡化許多操作。還要多一個指針指向前一個結點,并且尾指針不在置空,而且指向第一個結點。
二,隊列和棧
1)隊列特性
就像如圖的核酸檢測,你先進入隊列,你就能比別人先做完核酸離開。因此隊列的特性是先進先出。
2)棧的特性
棧的特性就像往一個一次只能拿出一個石頭的瓶子里面投石頭,你想要拿到最下面的石頭你就需要先拿出前面所有的石頭,因此棧的特性就是先進后出。
3)隊列用鏈表實現(xiàn)(源代碼及詳細講解)
1)隊列結構和功能實現(xiàn)前準備
和鏈表一樣,我們隊列也使用結構體指針的方法實現(xiàn),與鏈表實現(xiàn)大同小異,但會有一個另外的結構體用來存儲隊列的第一個元素指針的地址,和最后一個元素指針的地址,這樣方便我們接下來的各個功能實現(xiàn),可以省下很多代碼量。
#include<stdio.h>
#include<assert.h>
typedef int QDataType;//方便以后將隊列修改為其他類型
typedef struct QListNode
{
struct QListNode* _next;//下一個隊列的指針
QDataType _data;//數(shù)據元素
}QNode;//減少代碼長度
typedef struct Queue
{
QNode* _front;//隊列第一個元素指針
QNode* _rear;//隊列最后一個元素指針
}Queue;
2)初始化隊列
void QueueInit(Queue* q) {
q->_front = (QNode*)malloc(sizeof(QNode));//開辟空間
q->_front->_data = -1;//數(shù)據隨意初始化
q->_rear = q->_front ;//此時只有一個元素,頭和尾相等
}
3)入列數(shù)據
void QueuePush(Queue* q, QDataType data) {
q->_rear->_data = data;//從尾開始入列
q->_rear->_next = (QNode*)malloc(sizeof(QNode));//給下一個隊列分配空間
q->_rear = q->_rear->_next;//移動尾指針
}
4)出列數(shù)據
void QueuePop(Queue* q) {
assert(q->_front!=q->_rear );//防止出列空隊列
QNode* list = q->_front ;//保存頭指針,防止丟失
while (list->_next != q->_rear) {
list = list->_next;
}//找到尾指針
free(q->_rear);//釋放尾指針
q->_rear = list;//重新恢復尾指針
}
5)獲取隊列頭部元素?
QDataType QueueFront(Queue* q) {
assert(q->_front != q->_rear);
return q->_front->_data;
}
6)獲取隊列尾部元素
QDataType QueueBack(Queue* q) {
assert(q->_front != q->_rear);//判斷是否有至少兩個元素,防止數(shù)組越界
QNode* list = q->_front;//保存頭指針,防止丟失
while (list->_next != q->_rear) {
list = list->_next;
}//找到尾結點,隊列最后一個元素指針
return list->_data;
}
7)銷毀隊列元素
void QueueDestroy(Queue* q) {
while (q->_front != q->_rear) {
QNode* list = q->_front;//利用list來銷毀上一個指針,防止銷毀之后找不到下一個元素
q->_front = q->_front->_next;//頭指針換為下一個元素
free(list);//銷毀
}
free(q->_rear);//不要忘記還落下了一個尾結點
q->_front = NULL;
q->_rear = NULL;//置空,防止非法訪問
}
4)棧的代碼實現(xiàn)(提供另外一種思路,自己實現(xiàn))
之前說過棧就像往一次只夠拿一個石頭的瓶子里放石頭和取石頭,有沒有發(fā)現(xiàn)棧和數(shù)組有很大的相似,當我們打開這個思路,我們會發(fā)現(xiàn)如果用數(shù)組實現(xiàn)的話,我們的代碼思路和代碼量突然就小了很多。我這里只提供結構和功能實現(xiàn)前的準備,其他望諸君自己勤練。文章來源:http://www.zghlxwxcb.cn/news/detail-703186.html
#include<stdio.h>
#include<assert.h>
// 支持動態(tài)增長的棧
typedef int STDataType;
typedef struct Stack
{
STDataType* _a; //到時候用maolloc開辟空間,可以隨時調節(jié)數(shù)組大小
int _top; // 棧頂
int _capacity; // 容量
}Stack;
最后言:數(shù)據結構是需要大量題目來練手的,單純的理論知識是紙上談兵,真正實現(xiàn)的時候是變化萬千。牢記:紙上得來終覺淺,絕知此事要躬行。文章來源地址http://www.zghlxwxcb.cn/news/detail-703186.html
到了這里,關于數(shù)據結構零基礎入門篇(C語言實現(xiàn))的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!