日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

程序员修仙之路-数据结构之 CXO让我做一个计算器

發(fā)布時(shí)間:2023/12/4 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 程序员修仙之路-数据结构之 CXO让我做一个计算器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

菜菜呀,個(gè)稅最近改革了,我得重新計(jì)算你的工資呀,我需要個(gè)計(jì)算器,你開(kāi)發(fā)一個(gè)吧

CEO,CTO,CFO于一身的CXO

X總,咱不會(huì)買一個(gè)嗎?

菜菜

那不得花錢嗎,一塊錢也是錢呀··這個(gè)計(jì)算器支持加減乘除運(yùn)算就行,很簡(jiǎn)單

CEO,CTO,CFO于一身的CXO

(尼瑪)那能不能給我漲點(diǎn)工資呀?

菜菜

公司現(xiàn)在很困難,你這個(gè)計(jì)算器關(guān)系到公司的存亡,你要注意呀!!

CEO,CTO,CFO于一身的CXO

(關(guān)于撇開(kāi)話題佩服的五體投地)好吧X總,我盡快做

菜菜

給你一天時(shí)間,我這里著急要用

CEO,CTO,CFO于一身的CXO

.........

菜菜CXO的需求果然還在繼續(xù),深呼吸,深呼吸 .......

有人說(shuō)數(shù)據(jù)結(jié)構(gòu)是為算法服務(wù)的,我還要在加一句:數(shù)據(jù)結(jié)構(gòu)和算法都是為業(yè)務(wù)服務(wù)的!!


CXO的需求果然不同凡響,又讓菜菜想到了新的數(shù)據(jù)結(jié)構(gòu):


◆◆棧的特性◆◆


定義

棧(stack)又名堆棧,它是一種運(yùn)算受限的線性表。其限制是僅允許在表的一端進(jìn)行插入和刪除運(yùn)算。這一端被稱為棧頂,相對(duì)的,把另一端稱為棧底。向一個(gè)棧插入新元素又稱作進(jìn)棧、入?;驂簵?#xff0c;它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個(gè)棧刪除元素又稱作出?;蛲藯?#xff0c;它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。

棧作為一種數(shù)據(jù)結(jié)構(gòu),其中有幾個(gè)特性需要提起大家注意:


1.? 操作受限:何為操作受限?在棧的操作中,一般語(yǔ)言中針對(duì)棧的操作只有兩種:入棧和出棧。并且操作只發(fā)生在棧的頂部。 有的同學(xué)會(huì)問(wèn),我用其他數(shù)據(jù)結(jié)構(gòu)也一樣能實(shí)現(xiàn)棧的效果。不錯(cuò),但是每種數(shù)據(jù)結(jié)構(gòu)都有自己的使用場(chǎng)景,沒(méi)有一種絕對(duì)無(wú)用的數(shù)據(jù)結(jié)構(gòu)。

2.? 棧在數(shù)據(jù)結(jié)構(gòu)上屬于一種線性表,滿足后進(jìn)先出的原則。這也是棧的最大特性,幾乎大部分后進(jìn)先出的場(chǎng)景都可以使用棧這個(gè)容器。比如一個(gè)函數(shù)的調(diào)用過(guò)程中,局部變量的存儲(chǔ)就是棧原理。當(dāng)執(zhí)行一個(gè)函數(shù)結(jié)束的時(shí)候,局部變量其實(shí)最先釋放的是最后的局部變量。



◆◆實(shí)現(xiàn)◆◆


????????在內(nèi)存分布上棧是用什么實(shí)現(xiàn)的呢?既然棧是一種線性結(jié)構(gòu),也就說(shuō)可以用線性的內(nèi)存分布數(shù)據(jù)結(jié)構(gòu)來(lái)實(shí)現(xiàn)。


1. 數(shù)組實(shí)現(xiàn)棧(順序棧):數(shù)組是在內(nèi)存分布上連續(xù)的一種數(shù)據(jù)結(jié)構(gòu)。經(jīng)過(guò)以前的學(xué)習(xí),我們知道數(shù)組的容量是不變的。如果業(yè)務(wù)上可以知道一個(gè)棧的元素的最大數(shù)量,我們完全可以用數(shù)組來(lái)實(shí)現(xiàn)。為什么這么說(shuō)?因?yàn)閿?shù)組的擴(kuò)容在某些時(shí)候性能是比較低的。因?yàn)樾枰_(kāi)辟新空間,并發(fā)生復(fù)制過(guò)程。

class MyStack

? ? {

? ? ? ? //數(shù)組容器

? ? ? ? int[] container = new int[100];

? ? ? ? //棧頂元素的索引

? ? ? ? int TopIndex = -1;


? ? ? ? //入棧操作

? ? ? ? public void Push(int newValue)

? ? ? ? {

? ? ? ? ? ? if (TopIndex >= 99)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? return ;

? ? ? ? ? ? }

? ? ? ? ? ? TopIndex++;

? ? ? ? ? ? container[TopIndex] = newValue;

? ? ? ? }

? ? ? ? //出棧操作

? ? ? ? public int Pop()

? ? ? ? {

? ? ? ? ? ? if (TopIndex < 0)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? return 0;

? ? ? ? ? ? }

? ? ? ? ? ? var topValue = container[TopIndex];

? ? ? ? ? ? TopIndex--;

? ? ? ? ? ? return topValue;

? ? ? ? }

? ? }


2. 鏈表實(shí)現(xiàn)棧(鏈?zhǔn)綏?#xff09;:為了應(yīng)對(duì)數(shù)組的擴(kuò)容問(wèn)題,我們可以用鏈表來(lái)實(shí)現(xiàn)棧。棧的頂部元素永遠(yuǎn)指向鏈表的頭元素即可。具體代碼有興趣的同學(xué)可以實(shí)現(xiàn)一下。


由以上可以看出,棧其實(shí)是基于基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)之上的一個(gè)具體業(yè)務(wù)形式的封裝。即:先進(jìn)后出。


◆◆性能◆◆


????????基于數(shù)組的棧我們暫且只討論未發(fā)生數(shù)組重建的場(chǎng)景下。無(wú)論是數(shù)組實(shí)現(xiàn)還是鏈表實(shí)現(xiàn),我們發(fā)現(xiàn)棧的內(nèi)部其實(shí)是有一個(gè)指向棧頂元素的指針,不會(huì)發(fā)生遍歷數(shù)組或者鏈表的情形,所以棧的出棧操作時(shí)間復(fù)雜度為O(1)。

????????至于入棧,如果你看過(guò)我以前介紹數(shù)組和鏈表的文章,你可以知道,給一個(gè)數(shù)組下標(biāo)元素賦值的操作時(shí)間復(fù)雜度為O(1),在鏈表頭部添加一個(gè)元素的操作時(shí)間復(fù)雜度也是O(1)。所以無(wú)論是數(shù)組還是鏈表實(shí)現(xiàn)棧,入棧操作時(shí)間復(fù)雜度也是O(1)。并且棧只有入棧出棧兩種操作,比其他數(shù)據(jù)結(jié)構(gòu)有N個(gè)操作方法要簡(jiǎn)單很多,也不容易出錯(cuò)。

????????至于發(fā)生數(shù)組重建,copy全部數(shù)據(jù)的過(guò)程其實(shí)是一個(gè)順序棧最壞的時(shí)間復(fù)雜度,因?yàn)楹驮瓟?shù)組的元素個(gè)數(shù)n有關(guān),所以時(shí)間復(fù)雜度為O(n)


◆◆設(shè)計(jì)要點(diǎn)◆◆


????????那一個(gè)計(jì)算器怎么用棧來(lái)實(shí)現(xiàn)呢?其實(shí)很多計(jì)算器就是通過(guò)兩個(gè)棧來(lái)實(shí)現(xiàn)的,其中一個(gè)棧保存操作的數(shù),另一個(gè)棧保存運(yùn)算符。

????????我們從左到右遍歷表達(dá)式,當(dāng)遇到數(shù)字,我們直接壓入操作數(shù)棧;當(dāng)遇到操作符的時(shí)候,當(dāng)前操作符與操作符棧頂?shù)脑乇容^優(yōu)先級(jí)(先乘除后加減的原則)。如果當(dāng)前運(yùn)算符比棧頂運(yùn)算符優(yōu)先級(jí)高,那說(shuō)明不需要執(zhí)行棧頂運(yùn)算符運(yùn)算,我們直接將當(dāng)前運(yùn)算符也入棧;

????????如果當(dāng)前運(yùn)算符比棧頂運(yùn)算符優(yōu)先級(jí)低,那說(shuō)明該執(zhí)行棧頂運(yùn)算符的運(yùn)算了。然后出棧運(yùn)算符棧頂元素,數(shù)據(jù)棧頂兩個(gè)元素,然后進(jìn)行相關(guān)運(yùn)算,然后把運(yùn)算結(jié)果再次壓入數(shù)據(jù)棧。


◆◆來(lái)一發(fā)吧◆◆

golang版本

特別鳴謝公司朋友亮亮提供golang代碼


?1package?stack
?2
?3import?(
?4????"errors"
?5????"fmt"
?6)
?7
?8type?Stack?struct?{
?9????Element?[]interface{}?//Element
10}
11
12func?NewStack()?*Stack?{
13????return?&Stack{}
14}
15
16func?(stack?*Stack)?Push(value?...interface{})?{
17????stack.Element?=?append(stack.Element,?value...)
18}
19
20//返回下一個(gè)元素
21func?(stack?*Stack)?Top()?(value?interface{})?{
22????if?stack.Size()?>?0?{
23????????return?stack.Element[stack.Size()-1]
24????}
25????return?nil?//read?empty?stack
26}
27
28//返回下一個(gè)元素,并從Stack移除元素
29func?(stack?*Stack)?Pop()?(value?interface{})?{
30????if?stack.Size()?>?0?{
31????????d?:=?stack.Element[stack.Size()-1]
32????????stack.Element?=?stack.Element[:stack.Size()-1]
33????????return?d
34????}
35????return?nil
36}
37
38//交換值
39func?(stack?*Stack)?Swap(other?*Stack)?{
40????switch?{
41????case?stack.Size()?==?0?&&?other.Size()?==?0:
42????????return
43????case?other.Size()?==?0:
44????????other.Element?=?stack.Element[:stack.Size()]
45????????stack.Element?=?nil
46????case?stack.Size()?==?0:
47????????stack.Element?=?other.Element
48????????other.Element?=?nil
49????default:
50????????stack.Element,?other.Element?=?other.Element,?stack.Element
51????}
52????return
53}
54
55//修改指定索引的元素
56func?(stack?*Stack)?Set(idx?int,?value?interface{})?(err?error)?{
57????if?idx?>=?0?&&?stack.Size()?>?0?&&?stack.Size()?>?idx?{
58????????stack.Element[idx]?=?value
59????????return?nil
60????}
61????return?errors.New("Set失敗!")
62}
63
64//返回指定索引的元素
65func?(stack?*Stack)?Get(idx?int)?(value?interface{})?{
66????if?idx?>=?0?&&?stack.Size()?>?0?&&?stack.Size()?>?idx?{
67????????return?stack.Element[idx]
68????}
69????return?nil?//read?empty?stack
70}
71
72//Stack的size
73func?(stack?*Stack)?Size()?int?{
74????return?len(stack.Element)
75}
76
77//是否為空
78func?(stack?*Stack)?Empty()?bool?{
79????if?stack.Element?==?nil?||?stack.Size()?==?0?{
80????????return?true
81????}
82????return?false
83}
84
85//打印
86func?(stack?*Stack)?Print()?{
87????for?i?:=?len(stack.Element)?-?1;?i?>=?0;?i--?{
88????????fmt.Println(i,?"=>",?stack.Element[i])
89????}
90}
91//========================分割線==============================//
92package?calculator
93
94import?(
95????"calculator/stack"
96????"strconv"
97)
98
99type?Calculator?struct{}
100
101var?DataStack?*stack.Stack
102var?OperatorStack?*stack.Stack
103
104func?NewCalculator()?*Calculator?{
105????DataStack?=?stack.NewStack()
106????OperatorStack?=?stack.NewStack()
107????return?&Calculator{}
108}
109
110func?(c?*Calculator)?Cal(dataOrOperator?string)?int?{
111
112????if?data,?ok?:=?strconv.ParseInt(dataOrOperator,?10,?64);?ok?==?nil?{
113????????//如果是數(shù)據(jù)直接入數(shù)據(jù)棧
114????????//?fmt.Println(dataOrOperator)
115????????DataStack.Push(data)
116????}?else?{
117
118????????//如果是操作符,和棧頂操作符比較優(yōu)先級(jí),如果大于棧頂,則直接入棧,否則棧頂元素出棧?進(jìn)行操作
119????????if?OperatorStack.Size()?<=?0?{
120????????????OperatorStack.Push(dataOrOperator)
121????????}?else?{
122????????????//當(dāng)前運(yùn)算符的優(yōu)先級(jí)
123????????????currentOpePrecedence?:=?operatorPrecedence(dataOrOperator)
124????????????//當(dāng)前運(yùn)算符棧頂元素的優(yōu)先級(jí)
125????????????stackTopOpePrecedence?:=?operatorPrecedence(OperatorStack.Top().(string))
126????????????if?currentOpePrecedence?>?stackTopOpePrecedence?{
127????????????????//如果當(dāng)前運(yùn)算符的優(yōu)先級(jí)大于棧頂元素的優(yōu)先級(jí),則入棧
128????????????????OperatorStack.Push(dataOrOperator)
129????????????}?else?{
130????????????????//運(yùn)算符棧頂元素出棧,數(shù)據(jù)棧出棧兩個(gè)元素,然后進(jìn)行運(yùn)算
131????????????????stackOpe?:=?OperatorStack.Pop()
132????????????????data2?:=?DataStack.Pop()
133????????????????data1?:=?DataStack.Pop()
134
135????????????????ret?:=?calculateData(stackOpe.(string),?data1.(int64),?data2.(int64))
136????????????????DataStack.Push(ret)
137????????????????OperatorStack.Push(dataOrOperator)
138????????????}
139????????}
140????}
141????return?0
142}
143
144func?(c?*Calculator)?GetResult()?int64?{
145????var?ret?int64
146????for?{
147
148????????if?OperatorStack.Size()?>?0?{
149????????????stackOpe?:=?OperatorStack.Pop()
150????????????data2?:=?DataStack.Pop()
151????????????data1?:=?DataStack.Pop()
152
153????????????ret?=?calculateData(stackOpe.(string),?data1.(int64),?data2.(int64))
154
155????????????DataStack.Push(ret)
156????????}?else?{
157????????????break
158????????}
159????}
160
161????return?ret
162}
163
164func?calculateData(operatorString?string,?data1,?data2?int64)?int64?{
165????switch?operatorString?{
166????case?"+":
167????????return?data1?+?data2
168????case?"-":
169????????return?data1?-?data2
170????case?"*":
171????????return?data1?*?data2
172????case?"/":
173????????return?data1?+?data2
174????default:
175????????return?0
176????}
177}
178
179func?operatorPrecedence(a?string)?int?{
180????i?:=?0
181????switch?a?{
182????case?"+":
183????????i?=?1
184????case?"-":
185????????i?=?1
186????case?"*":
187????????i?=?2
188????case?"/":
189????????i?=?2
190????}
191????return?i
192}
193//========================分割線==============================//
194package?main
195
196import?(
197????"calculator/calculator"
198????"flag"
199????"fmt"
200)
201
202var?(
203????inputStr?=?flag.String("input",?"",?"請(qǐng)輸入...")
204)
205
206func?main()?{
207????flag.Parse()
208
209????var?lstAllData?[]string
210????var?tempData?string
211
212????rs?:=?[]rune(*inputStr)
213????for?i?:=?0;?i?<?len(rs);?i++?{
214????????if?string(rs[i])?==?"+"?||?string(rs[i])?==?"-"?||?string(rs[i])?==?"*"?||?string(rs[i])?==?"/"?{
215????????????lstAllData?=?append(lstAllData,?tempData)
216????????????lstAllData?=?append(lstAllData,?string(rs[i]))
217????????????tempData?=?""
218????????}?else?{
219????????????tempData?+=?string(rs[i])
220????????}
221????????if?i?==?len(rs)-1?{
222????????????lstAllData?=?append(lstAllData,?tempData)
223????????}
224????}
225
226????ca?:=?calculator.NewCalculator()
227????for?_,?v?:=?range?lstAllData?{
228????????ca.Cal(v)
229????}
230????ret?:=?ca.GetResult()
231????fmt.Println(ret)
232}



c#版本

?1class?Program
?2????{
?3????????static?void?Main(string[]?args)
?4????????
{
?5????????????List<string>?lstAllData?=?new?List<string>();
?6????????????//讀取輸入的表達(dá)式,并整理
?7????????????string?inputStr?=?Console.ReadLine();
?8????????????string?tempData?=?"";
?9????????????for?(int?i?=?0;?i?<?inputStr.Length;?i++)
10????????????{
11????????????????if?(inputStr[i]?==?'+'?||?inputStr[i]?==?'-'?||?inputStr[i]?==?'*'?||?inputStr[i]?==?'/')
12????????????????{
13????????????????????lstAllData.Add(tempData);
14????????????????????lstAllData.Add(inputStr[i].ToString());
15????????????????????tempData?=?"";
16????????????????}
17????????????????else
18????????????????{
19????????????????????tempData?+=?inputStr[i];
20????????????????}
21????????????????if(i==?inputStr.Length?-?1)
22????????????????{
23????????????????????lstAllData.Add(tempData);
24????????????????}
25????????????}
26????????????foreach?(var?item?in?lstAllData)
27????????????{
28????????????????Calculator.Cal(item.ToString());
29????????????}
30????????????var?ret?=?Calculator.GetResult();
31????????????Console.WriteLine(ret);
32????????????Console.Read();
33????????}
34
35????}
36????//計(jì)算器
37????class?Calculator
38????{
39????????//存放計(jì)算數(shù)據(jù)的棧
40????????static?Stack<int>?DataStack?=?new?Stack<int>();
41????????//存放操作符的棧
42????????static?Stack<string>?OperatorStack?=?new?Stack<string>();
43????????public?static?int?Cal(string?dataOrOperator)
44????????
{
45????????????int?data;
46????????????bool?isData?=?int.TryParse(dataOrOperator,?out?data);
47????????????if?(isData)
48????????????{
49????????????????//如果是數(shù)據(jù)直接入數(shù)據(jù)棧
50????????????????DataStack.Push(data);
51????????????}
52????????????else
53????????????{
54????????????????//如果是操作符,和棧頂操作符比較優(yōu)先級(jí),如果大于棧頂,則直接入棧,否則棧頂元素出棧?進(jìn)行操作
55????????????????if?(OperatorStack.Count?<=?0)
56????????????????{
57????????????????????OperatorStack.Push(dataOrOperator);
58????????????????}
59????????????????else
60????????????????{
61????????????????????//當(dāng)前運(yùn)算符的優(yōu)先級(jí)
62????????????????????var?currentOpePrecedence?=?OperatorPrecedence(dataOrOperator);
63????????????????????//當(dāng)前運(yùn)算符棧頂元素的優(yōu)先級(jí)
64????????????????????var?stackTopOpePrecedence?=?OperatorPrecedence(OperatorStack.Peek());
65????????????????????if?(currentOpePrecedence?>?stackTopOpePrecedence)
66????????????????????{
67????????????????????????//如果當(dāng)前運(yùn)算符的優(yōu)先級(jí)大于棧頂元素的優(yōu)先級(jí),則入棧
68????????????????????????OperatorStack.Push(dataOrOperator);
69????????????????????}
70????????????????????else
71????????????????????{
72????????????????????????//運(yùn)算符棧頂元素出棧,數(shù)據(jù)棧出棧兩個(gè)元素,然后進(jìn)行運(yùn)算
73????????????????????????var?stackOpe?=?OperatorStack.Pop();
74????????????????????????var?data2?=?DataStack.Pop();
75????????????????????????var?data1?=?DataStack.Pop();
76????????????????????????var?ret?=?CalculateData(stackOpe,?data1,?data2);
77????????????????????????DataStack.Push(ret);
78????????????????????????OperatorStack.Push(dataOrOperator);
79????????????????????}
80????????????????}
81????????????}
82????????????return?0;
83????????}
84????????//獲取表達(dá)式最后的計(jì)算結(jié)果
85????????public?static?int?GetResult()
86????????
{
87????????????var?ret?=?0;
88????????????while?(OperatorStack.Count?>?0)
89????????????{
90????????????????var?stackOpe?=?OperatorStack.Pop();
91????????????????var?data2?=?DataStack.Pop();
92????????????????var?data1?=?DataStack.Pop();
93????????????????ret?=?CalculateData(stackOpe,?data1,?data2);
94????????????????DataStack.Push(ret);
95????????????}
96????????????return?ret;
97????????}
98????????//根據(jù)操作符進(jìn)行運(yùn)算,這里可以抽象出接口,請(qǐng)自行實(shí)現(xiàn)
99????????static?int?CalculateData(string?operatorString,?int?data1,?int?data2)
100????????
{
101????????????switch?(operatorString)
102????????????{
103????????????????case?"+":
104????????????????????return?data1?+?data2;
105????????????????case?"-":
106????????????????????return?data1?-?data2;
107????????????????case?"*":
108????????????????????return?data1?*?data2;
109????????????????case?"/":
110????????????????????return?data1?+?data2;
111????????????????default:
112????????????????????return?0;
113????????????}
114????????}
115????????//獲取運(yùn)算符優(yōu)先級(jí)
116????????public?static?int?OperatorPrecedence(string?a)????//操作符優(yōu)先級(jí)
117????????
{
118????????????int?i?=?0;
119????????????switch?(a)
120????????????{
121????????????????case?"+":?i?=?1;?break;
122????????????????case?"-":?i?=?1;?break;
123????????????????case?"*":?i?=?2;?break;
124????????????????case?"/":?i?=?2;?break;
125????????????}
126????????????return?i;
127
128????????}
129????}



程序猿修仙之路--數(shù)據(jù)結(jié)構(gòu)之設(shè)計(jì)高性能訪客記錄系統(tǒng)●程序猿修仙之路--算法之快速排序到底有多快程序猿修仙之路--數(shù)據(jù)結(jié)構(gòu)之你是否真的懂?dāng)?shù)組?

●程序猿修仙之路--算法之希爾排序!

●程序員修仙之路--算法之插入排序!

●程序員修仙之路--算法之選擇排序!


總結(jié)

以上是生活随笔為你收集整理的程序员修仙之路-数据结构之 CXO让我做一个计算器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。