contributed by < ioksengtan
>
$ gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.5 (clang-1205.0.22.11)
Target: arm64-apple-darwin20.5.0
Thread model: posix
q_new
: 建立新的「空」佇列
q_size
: 計算目前佇列的節點總量q_insert_head
: 在佇列開頭 (head) 插入 (insert) 給定的新節點 (以 LIFO 準則)q_insert_tail
: 在佇列尾端 (tail) 插入 (insert) 給定的新節點 (以 FIFO 準則)
q_remove_head
: 在佇列開頭 (head) 移去 (remove) 給定的節點
q_remove_tail
: 在佇列尾端 (tail) 移去 (remove) 給定的節點q_free
: 釋放佇列所佔用的記憶體q_reverse
: 以反向順序重新排列鏈結串列,該函式不該配置或釋放任何鏈結串列節點,換言之,它只能重排已經存在的節點q_delete_mid
: 移走佇列中間的節點
q_delete_dup
: 在已經排序的狀況,移走佇列中具備重複內容的節點
q_swap
: 交換佇列中鄰近的節點
q_sort
: 以遞增順序來排序鏈結串列的節點Improve your writing! It is supposed to be an official document.
jserv
Thanks a lot jserv for feedback.
I will continue refining my documentation.
ioksengtan
list_for_each
int q_size(struct list_head *head)
{
if (!head)
return 0;
int len = 0;
struct list_head *li;
list_for_each (li, head)
len++;
return len;
}
struct list_head *q_new()
{
element_t *q = malloc(sizeof(element_t));
if (q == NULL) {
return NULL;
}
INIT_LIST_HEAD(&q->list);
return &q->list;
}
cmd> new
Freeing old queue
l = NULL
ERROR: Freed queue, but 2 blocks are still allocated
l = []
reference: https://myao0730.blogspot.com/2016/12/linux.html
using provided list_add() in list.h
/**
* list_add() - Add a list node to the beginning of the list
* @node: pointer to the new node
* @head: pointer to the head of the list
*/
static inline void list_add(struct list_head *node, struct list_head *head)
{
struct list_head *next = head->next;
next->prev = node;
node->next = next;
node->prev = head;
head->next = node;
}
bool q_insert_head(struct list_head *head, char *s)
{
if (!head)
return false;
element_t *ele = malloc(sizeof(element_t));
if (!ele)
return false;
ele->value = malloc(sizeof(s));
memset(ele->value, '\0', strlen(ele->value));
strncpy(ele->value, s, strlen(s));
list_add(&ele->list, head);
return true;
}
cmd> new
l = []
cmd> ih test
l = [test]
cmd> ih test2
l = [test2 test]
reuse list_add_tail in list.h
bool q_insert_tail(struct list_head *head, char *s)
{
if (!head)
return false;
element_t *ele = malloc(sizeof(element_t));
if (!ele)
return false;
ele->value = malloc(sizeof(s));
memset(ele->value, '\0', strlen(ele->value));
strncpy(ele->value, s, strlen(s));
list_add_tail(&ele->list, head);
return true;
}
cmd> new
l = []
cmd> it test
l = [test]
cmd> free
ERROR: Corruption detected in block with address 0x12ef04130 when attempting to free it
l = NULL
Corruption detected:
ele->value = malloc(sizeof(s));
memset(ele->value, '\0', strlen(ele->value));
strncpy(ele->value, s, strlen(s));
No Corruption detection:
ele->value = strdup(s);
Revised implementation of q_insert_tail
bool q_insert_tail(struct list_head *head, char *s)
{
if (!head)
return false;
element_t *ele = malloc(sizeof(element_t));
if (!ele)
return false;
ele->value = strdup(s);
list_add_tail(&ele->list, head);
return true;
}
You must explain your observations and reactions.
jserv
Thanks alot jserv for feedback,
I am cooking those information then document it later.
ioksengtan
Then there is no corruption
cmd> new
l = []
cmd> it test
l = [test]
cmd> rt
Removed test from queue
l = []
cmd> it test
l = [test]
cmd> free
l = NULL
(1) list_add_tail(&(ele->list), head);
(2) list_add_tail(&ele->list, head);
using (1), will fail the static analysis when git commit.
lab0-c git:(master) ✗ git commit -a
Following files need to be cleaned up:
queue.c
queue.c:118:5: error: Memory leak: ele [memleak]
return true;
^
cmd> new
l = []
cmd> it test
l = [test]
cmd> it test2
l = [test test2]
cmd> it test3
l = [test test2 test3]
element_t *q_remove_head(struct list_head *head, char *sp, size_t bufsize)
{
if (!head || list_empty(head))
return NULL;
if (sp) {
element_t *e = list_first_entry(head, element_t, list);
size_t len = strlen(e->value);
len = (bufsize-1)>len?len:(bufsize-1);
memcpy(sp, e->value, len);
sp[len] = '\0';
list_del(&e->list);
return e;
}
return NULL;
}
cmd> new
l = []
cmd> ih test
l = [test]
cmd> ih test2
l = [test2 test]
cmd> rh
Removed test2 from queue
l = [test]
void q_free(struct list_head *l)
{
if (l == NULL) {
return;
}
struct list_head *node = l->next;
while (node != l) {
element_t *e = container_of(node, element_t, list);
node = node->next;
q_release_element(e);
}
// cppcheck-suppress nullPointer
element_t *head = container_of(l, element_t, list);
free(head);
}
Following implementation is wrongful, causing segmentation fault.
if (!l)
return;
// iterate over the list entries and remove it
element_t *entry, *safe;
list_for_each_entry_safe (entry, safe, l, list)
q_release_element(entry);
free(l);
cmd> new
l = []
cmd> ih test
l = [test]
cmd> ih test2
l = [test2 test]
cmd> free
ERROR: Attempted to free unallocated block. Address = 0x15bf042b8
ERROR: Attempted to free unallocated or corrupted block. Address = 0x15bf042b8
Segmentation fault occurred. You dereferenced a NULL or invalid pointer
when number is even (N=4)
if front->next = end, remove node3
when number is odd (N=3)
if front = end, remove node2
bool q_delete_mid(struct list_head *head)
{
// https://leetcode.com/problems/delete-the-middle-node-of-a-linked-list/
if (!head || list_empty(head)) {
return false;
}
struct list_head *front = head->next;
struct list_head *end = head->prev;
while (true) {
if (front == end || front->next == end){
list_del(front);
q_release_element(list_entry(front, element_t, list));
break;
}
front = front->next;
end = end->prev;
}
return true;
}
worst case:
看到一些同學實作quick sort有遇到效能的問題。
複習了sort 的時空複雜度,的確quick sort 的最差情境會是N^2。
merge sort原理: