Rumah > Artikel > pembangunan bahagian belakang > Struktur data Python dan pembelajaran algoritma baris gilir dua hujung
Artikel ini membawa anda pengetahuan yang berkaitan tentang python Ia terutamanya memperkenalkan isu yang berkaitan dengan baris gilir dua hujung, termasuk konsep asas baris gilir dua hujung, pelaksanaan baris gilir dua hujung dan dua hujung. Pemakaian baris gilir akhir, saya harap ia akan membantu semua orang.
Pembelajaran yang disyorkan: Tutorial python
Baris gilir dua hujung ialah data linear lain struktur. Walaupun ia juga merupakan jadual linear terhad, tidak seperti tindanan dan baris gilir, baris gilir dua hujung mempunyai sedikit sekatan operasi asasnya juga merupakan subset operasi jadual linear, tetapi dari perspektif jenis data, ia berbeza daripada jadual Linear sangat berbeza. . Bahagian ini akan memperkenalkan definisi baris gilir dua hujung dan pelaksanaannya yang berbeza, dan memberikan beberapa aplikasi praktikal baris gilir dua hujung.
Dengan mengkaji bahagian ini, anda harus menguasai kandungan berikut:
Baris gilir dua hujung (double-end queue
, deque
) juga merupakan senarai linear di mana operasi sisipan dan pemadaman dihadkan kepada kedua-dua hujung jujukan, tetapi tidak seperti tindanan dan baris gilir, baris gilir dua hujung mempunyai sedikit sekatan , untuk baris gilir dua hujung, kedua-dua ekor (rear
) dan kepala (front
) baris gilir membenarkan elemen untuk dimasukkan dan dipadamkan. Elemen baharu boleh ditambah pada kepala atau ekor baris gilir. Begitu juga, elemen sedia ada boleh dialih keluar dari kedua-dua hujung. Dari satu segi, baris gilir dua hujung boleh dianggap sebagai gabungan timbunan dan baris gilir.
Walaupun baris gilir dua hujung mempunyai banyak ciri tindanan dan baris gilir, ia tidak memerlukan mengikut LIFO
prinsip dan FIFO
prinsip yang ditakrifkan oleh kedua-dua struktur data ini .
Selain menambah dan mengalih keluar elemen, baris gilir dua hujung juga mempunyai operasi tambahan seperti permulaan, penghakiman kosong baris gilir dan penentuan panjang giliran. Khususnya, jenis data abstrak deque ditakrifkan seperti berikut:
Operasi asas:
1. __itit__(): Mulakan deque
Buat deque kosong
2. size(): Dapatkan dan kembalikan bilangan elemen n
Jika baris gilir dua hujung kosong, kembalikan integer 0
3. isempty(): Tentukan sama ada baris gilir dua hujung kosong
Nilai sama ada elemen disimpan dalam baris gilir dua hujung
4. addfront(data): Tambah elemen pada kepala baris gilir dua hujung
Masukkan data elemen ke dalam kepala baris gilir
5. addrear(data): Double Tambah elemen pada penghujung baris gilir dua hujung
Masukkan data elemen ke penghujung baris gilir
6. removefront(): Padamkan elemen kepala double- baris gilir berakhir
Padam dan kembalikan elemen kepala baris gilir
7. removerear(): Padam Elemen ekor baris gilir dua hujung
Padam dan kembalikan elemen ekor baris gilir
Seperti baris gilir biasa, baris gilir dua hujung juga mempunyai storan berurutan dan Terdapat dua kaedah perwakilan storan storan rantai.
, apabila elemen dimasukkan ke dalam baris gilir, front
, dan apabila elemen dinyah gilir, rear
Pada masa yang sama, untuk menggunakan semula ruang kosong, kami menganggap ruang gelang ekor daripada deque berurutan, Ruang terakhir dan ruang pertama dianggap sebagai ruang berterusan (atas sebab tertentu, sila rujuk front=rear=0
rear 加 1
front 加 1
Begitu juga, berjujukan baris gilir dua hujung boleh menjadi panjang tetap dan Panjang dinamik, apabila baris gilir dua hujung penuh, baris gilir dua hujung berurutan tetap panjang akan membuang baris gilir dua hujung penuh pengecualian, dan baris gilir dua hujung berurutan dinamik akan secara dinamik memohon ruang kosong.
2.1.1 Permulaan deque
, dan deque
dan max_size
digunakan untuk merekod indeks elemen kepala dan elemen ekor masing-masing: queue
class Deque: def __init__(self, max_size=6): self.max_size = max_size self.deque = [None] * self.max_size self.front = 0 self.rear = 0
Oleh kerana front
dan rear
digunakan untuk merekod indeks elemen kepala dan elemen ekor masing-masing , jadi kami Panjang baris gilir dua hujung boleh dikira dengan mudah pada masa yang sama, kita perlu mempertimbangkan bahawa baris gilir dua hujung ialah barisan bulat front
mungkin lebih besar daripada rear
dan tidak boleh secara langsung melalui rear-front
. Kita perlu menggunakan pengiraan formula untuk menyelesaikan masalah ini:
Python
dilaksanakan seperti berikut:
def size(self): return (self.rear-self.front+self.max_size) % self.max_size
Menurut front
dan rear
Nilai boleh dengan mudah menentukan sama ada baris gilir dua hujung kosong:
def isempty(self): return self.rear==self.front
Mengikut nilai front
dan rear
Nilai dengan mudah boleh menentukan sama ada terdapat ruang kosong dalam dua baris gilir -berakhir:
def isfull(self): return ((self.rear+1) % self.max_size == self.front)
Apabila menambah elemen, anda perlu terlebih dahulu menentukan baris gilir dua hujung Sama ada terdapat ruang kosong dalam baris gilir akhir, dan kemudian bergantung pada sama ada baris gilir dua hujung ialah baris gilir dua hujung berurutan panjang tetap atau baris gilir dua hujung berjujukan dinamik, operasi menambah elemen adalah sedikit berbeza:
[Tambah operasi Elemen baris gilir dua hujung jujukan panjang tetap] Jika baris gilir penuh, pengecualian akan dilemparkan:
# 注意队头和队尾修改索引的添加元素的不同顺序 def addrear(self, data): if not self.isfull(): self.deque[self.rear] = data self.rear = (self.rear+1) % self.max_size else: raise IndexError("Full Deque Exception") def addfront(self, data): if self.isfull(): self.resize() if self.isempty(): # 当Struktur data Python dan pembelajaran algoritma baris gilir dua hujung self.deque[self.rear] = data self.rear = (self.rear+1) % self.max_size else: self.front = (self.front - 1 + self.max_size) % self.max_size self.deque[self.front] = data
[Tambah operasi elemen jujukan dinamik deque] Jika deque penuh, mohon ruang yang baharu dahulu, dan kemudian lakukan operasi tambah:
def resize(self): new_size = 2 * self.max_size new_deque = [None] * new_size d = new_size - self.max_size for i in range(self.max_size): new_deque[(self.front+i+d) % new_size] = self.deque[(self.front+i) % self.max_size] self.deque = new_deque self.front = (self.front+d) % new_size self.max_size = new_size # 注意队头和队尾修改索引的添加元素的不同顺序 def addrear(self, data): if self.isfull(): self.resize() self.deque[self.rear] = data self.rear = (self.rear+1) % self.max_size def addfront(self, data): if self.isfull(): self.resize() self.front = (self.front - 1 + self.max_size) % self.max_size self.deque[self.front] = data
Sama seperti baris gilir berjujukan dinamik, kita juga perlu mempertimbangkan indeks selepas menyalin, jika tidak, mungkin terdapat ruang kosong yang tidak boleh digunakan:
Kerumitan masa untuk menambah elemen ialah O(1 ). Walaupun apabila baris gilir dua hujung berjujukan dinamik penuh, elemen dalam baris gilir dua hujung yang asal perlu disalin ke baris gilir dua hujung baharu dahulu, dan kemudian elemen baharu ditambah Walau bagaimanapun, rujuk kepada pengenalan jujukan operasi tambah jadual dalam "Jadual Jujukan dan Pelaksanaan Operasinya", Sejak jumlah masa n
tambah operasi elemenT( n) dan O( n ) adalah berkadar dengan (1) . 2.1.6 Padamkan elemen di kepala atau ekor baris gilir Jika baris gilir dua hujung tidak kosong, padam dan kembalikan elemen akhir yang ditentukan:
Satu lagi perwakilan storan baris gilir dua hujung ialah menggunakan struktur storan berantai, jadi ia juga sering dipanggil baris gilir dua hujung berantai, di mana operasi
dan operasi# 注意队头和队尾修改索引的删除元素的不同顺序 def removefront(self): if not self.isempty(): result = self.deque[self.front] self.front = (self.front+1) % self.max_size return result else: raise IndexError("Empty Deque Exception") def removerear(self): if not self.isempty(): self.rear = (self.rear - 1 + self.max_size) % self.max_size result = self.deque[self.rear] return result else: raise IndexError("Empty Deque Exception")dilaksanakan dengan memasukkan elemen di kepala dan ekor senarai terpaut masing-masing, manakala operasi
addfront
addrear
2.2.1 Nod baris gilir dua hujungremovefront
removerear
Pelaksanaan nod baris gilir dua hujung tidak berbeza daripada senarai terpaut dua kali:
2.2.2 Permulaan baris gilir dua hujung
kedua-duanya menghala ke
, dan mulakan baris gilir dua hujung Panjang:class Node: def __init__(self, data=None): self.data = data self.next = None def __str__(self): return str(self.data)2.2.3 Cari panjang baris gilir dua hujung
front
Nilai yang dikembalikan oleh rear
digunakan untuk mencari panjang daripada baris gilir dua hujung. Jika tiada atribut None
, ia diperlukan Panjang baris gilir dua hujung boleh diperolehi dengan merentasi keseluruhan senarai terpaut:
class Deque: def __init__(self): self.front = None self.rear = None self.num = 0
Mengikut panjang baris gilir dua hujung, ia boleh dinilai dengan mudah sama ada baris gilir dua hujung kosong: num
num
def size(self): return self.num
penunjuk, dan juga ubah suai
dandef isempty(self): return self.num penunjuk nod; jika baris gilir dua hujung kosong sebelum menambah elemen, pemprosesan yang sepadan perlu dilakukan: <h4> <pre class="brush:php;toolbar:false"> def addrear(self, data): node = Node(data) # 如果添加元素前Struktur data Python dan pembelajaran algoritma baris gilir dua hujung为空,则添加结点时,需要将front指针也指向该结点 if self.front is None: self.rear = node self.front = node else: node.previous = self.rear self.rear.next = node self.rear = node self.num += 1 def addfront(self, data): node = Node(data) # 如果添加元素前Struktur data Python dan pembelajaran algoritma baris gilir dua hujung为空,则添加结点时,需要将rear指针也指向该结点 if self.rear is None: self.front = node self.rear = node else: node.next = self.front self.front.previous = node self.front = node self.num += 1
若Struktur data Python dan pembelajaran algoritma baris gilir dua hujung不空,可以从删除队头或队尾元素并返回,删除操作需要更新队头指针 front
以及尾指针 rear
,同时也要修改结点的 next
和 previous
指针,若出队元素尾队中最后一个结点,还需要进行相应处理:
def removefront(self): if self.isempty(): raise IndexError("Empty Queue Exception") result = self.front.data self.front = self.front.next self.num -= 1 if self.isempty(): self.rear = self.front else: # 若删除操作完成后,Struktur data Python dan pembelajaran algoritma baris gilir dua hujung不为空,将 front 指针的前驱指针指向 None self.front.previous = None return result def removerear(self): if self.isempty(): raise IndexError("Empty Queue Exception") result = self.rear.data self.rear = self.rear.previous self.num -= 1 if self.isempty(): self.front = self.rear else: # 若删除操作完成后,Struktur data Python dan pembelajaran algoritma baris gilir dua hujung不为空,将 rear 指针的后继指针指向 None self.rear.next = None return result
Struktur data Python dan pembelajaran algoritma baris gilir dua hujung的不同实现对比与栈的不同实现类似,可以参考《栈及其操作实现》。
接下来,我们首先测试上述实现的Struktur data Python dan pembelajaran algoritma baris gilir dua hujung,以验证操作的有效性,然后利用实现的基本操作来解决实际算法问题。
首先初始化一个顺序Struktur data Python dan pembelajaran algoritma baris gilir dua hujung deque
,然后测试相关操作:
# 初始化一个最大长度为5的Struktur data Python dan pembelajaran algoritma baris gilir dua hujungdq = Deque(5)print('Struktur data Python dan pembelajaran algoritma baris gilir dua hujung空?', dq.isempty())for i in range(3): print('队头添加元素:', 2*i) dq.addfront(2*i) print('队尾添加元素:', 2*i+1) dq.addrear(2*i+1)print('Struktur data Python dan pembelajaran algoritma baris gilir dua hujung长度为:', dq.size())for i in range(3): print('队尾删除元素:', dq.removerear()) print('队头删除元素:', dq.removefront())print('Struktur data Python dan pembelajaran algoritma baris gilir dua hujung长度为:', dq.size())
测试程序输出结果如下:
Struktur data Python dan pembelajaran algoritma baris gilir dua hujung空? True队头添加元素: 0队尾添加元素: 1队头添加元素: 2队尾添加元素: 3队头添加元素: 4队尾添加元素: 5Struktur data Python dan pembelajaran algoritma baris gilir dua hujung长度为: 6队尾删除元素: 5队头删除元素: 4队尾删除元素: 3队头删除元素: 2队尾删除元素: 1队头删除元素: 0Struktur data Python dan pembelajaran algoritma baris gilir dua hujung长度为: 0
首先初始化一个链Struktur data Python dan pembelajaran algoritma baris gilir dua hujung queue
,然后测试相关操作:
# 初始化新队列dq = Deque()print('Struktur data Python dan pembelajaran algoritma baris gilir dua hujung空?', dq.isempty())for i in range(3): print('队头添加元素:', i) dq.addfront(2*i) print('队尾添加元素:', i+3) dq.addrear(2*i+1)print('Struktur data Python dan pembelajaran algoritma baris gilir dua hujung长度为:', dq.size())for i in range(3): print('队尾删除元素:', dq.removerear()) print('队头删除元素:', dq.removefront())print('Struktur data Python dan pembelajaran algoritma baris gilir dua hujung长度为:', dq.size())
测试程序输出结果如下:
Struktur data Python dan pembelajaran algoritma baris gilir dua hujung空? True队头添加元素: 0队尾添加元素: 3队头添加元素: 1队尾添加元素: 4队头添加元素: 2队尾添加元素: 5Struktur data Python dan pembelajaran algoritma baris gilir dua hujung长度为: 6队尾删除元素: 5队头删除元素: 4队尾删除元素: 3队头删除元素: 2队尾删除元素: 1队头删除元素: 0Struktur data Python dan pembelajaran algoritma baris gilir dua hujung长度为: 0
[1] 给定一字符串 string
(如:abamaba),检查其是否为回文。
使用Struktur data Python dan pembelajaran algoritma baris gilir dua hujung可以快速检查一字符串是否为回文序列,只需要将字符串中字符依次入队,然后从Struktur data Python dan pembelajaran algoritma baris gilir dua hujung两端依次弹出元素,对比它们是否相等:
def ispalindrome(string): deque = Deque() for ch in string: deque.addfront(ch) flag = True while deque.size() > 1 and flag: ch1 = deque.removefront() ch2 = deque.removerear() if ch1 != ch2: flag = False return flag
验证算法有效性:
print('abcba是否为回文序列:', ispalindrome('abcba'))print('charaahc是否为回文序列:', ispalindrome('charaahc'))
结果输出如下:
abcba是否为回文序列: True charaahc是否为回文序列: False
推荐学习:python教程
Atas ialah kandungan terperinci Struktur data Python dan pembelajaran algoritma baris gilir dua hujung. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!