双链表的实现 基于go语言实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 package main import "fmt" // Node 定义双链表节点 type Node struct { data interface{} prev *Node next *Node } // DoublyLinkedList 定义双链表 type DoublyLinkedList struct { head *Node tail *Node size int } // InsertTail 向链表尾部插入节点 func (dll *DoublyLinkedList) InsertTail(data interface{}) { newNode := &Node{data: data} if dll.size == 0 { dll.head = newNode dll.tail = newNode } else { dll.tail.next = newNode newNode.prev = dll.tail dll.tail = newNode } dll.size++ } // InsertHead 向链表头部插入节点 func (dll *DoublyLinkedList) InsertHead(data interface{}) { newNode := &Node{data: data} if dll.size == 0 { dll.head = newNode dll.tail = newNode } else { newNode.next = dll.head dll.head.prev = newNode dll.head = newNode } dll.size++ } // Remove 删除节点 func (dll *DoublyLinkedList) Remove(node *Node) { if node.prev != nil { node.prev.next = node.next } else { dll.head = node.next } if node.next != nil { node.next.prev = node.prev } else { dll.tail = node.prev } node.prev = nil node.next = nil dll.size-- } // Display 打印双链表 func (dll *DoublyLinkedList) Display() { curr := dll.head for curr != nil { fmt.Print(curr.data, " ") curr = curr.next } fmt.Println() } func main() { dll := DoublyLinkedList{} dll.InsertTail(1) dll.InsertTail(2) dll.InsertHead(0) dll.Display() // 应该输出:0 1 2 // 删除节点 headNode := dll.head dll.Remove(headNode) dll.Display() // 应该输出:1 2 }
基于c语言实现双链表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 #include <stdio.h> #include <stdlib.h> // 定义双链表节点结构 typedef struct Node { int data; struct Node* prev; struct Node* next; } Node; // 创建一个新节点 Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); if (newNode == NULL) { printf("内存分配失败"); exit(1); } newNode->data = data; newNode->prev = NULL; newNode->next = NULL; return newNode; } // 在双链表前插入节点 void insertFront(Node** head, int data) { Node* newNode = createNode(data); newNode->next = *head; if (*head != NULL) { (*head)->prev = newNode; } *head = newNode; } // 在双链表后插入节点 void insertRear(Node** head, int data) { Node* newNode = createNode(data); if (*head == NULL) { *head = newNode; return; } Node* last = *head; while (last->next != NULL) { last = last->next; } last->next = newNode; newNode->prev = last; } // 删除双链表前的节点 void deleteFront(Node** head) { if (*head == NULL) { printf("链表为空,无法删除"); return; } Node* temp = *head; *head = (*head)->next; if (*head != NULL) { (*head)->prev = NULL; } free(temp); } // 删除双链表后的节点 void deleteRear(Node** head) { if (*head == NULL) { printf("链表为空,无法删除"); return; } Node* secondLast = *head; while (secondLast->next->next != NULL) { secondLast = secondLast->next; } Node* temp = secondLast->next; secondLast->next = NULL; free(temp); } // 打印双链表 void printList(Node* node) { while (node != NULL) { printf("%d ", node->data); node = node->next; } printf("\n"); } int main() { Node* head = NULL; insertFront(&head, 10); insertFront(&head, 20); insertRear(&head, 30); insertRear(&head, 40); printList(head); // 输出:20 10 30 40 deleteFront(&head); deleteRear(&head); printList(head); // 输出:10 30 return 0; }
区别:
c语言的双链表 我们要清楚 改变了头节点 所以要传入二级指针 才能正确的记录到头指针的变化
而Go语言,因为 Go 中的切片、映射和通道等是引用类型,它们在函数参数传递时本身就是按引用传递的,不需要通过指针的指针(二级指针)来实现修改。这实际上是 Go 语言的一个特性:切片、映射和通道在函数间传递时,共享底层数据结构,因此不需要额外的二级指针。
栈的c语言实现 1.数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include<stdio.h> #include<stdbool.h> typedef struct Stack { int data[10]; int top; } Stack; void InitStack(Stack* stack) { stack->top = -1; } bool IsFull(Stack* stack) { return stack->top == 9; } bool IsEmpty(Stack* stack) { return stack->top == -1; } bool push(Stack* stack, int data) { if (IsFull(stack)) { printf("栈已经满了不能执行入栈操作\n"); return false; } stack->data[++stack->top] = data; return true; } int pop(Stack* stack) { if (IsEmpty(stack)) { printf("栈已经空了不能出栈\n"); return -1; } return stack->data[stack->top--]; } void Println(Stack* stack) { printf("栈中元素:"); for (int i = stack->top; i >= 0 ; i--) { printf("%d ", stack->data[i]); } printf("\n"); } int main() { Stack stack; InitStack(&stack); push(&stack, 1); push(&stack, 2); push(&stack, 3); push(&stack, 4); Println(&stack); //pop(&stack); pop(&stack); pop(&stack); // pop(&stack); Println(&stack); return 0; }
2.链表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef struct stack { int data; struct stack* next; } Stack; void InitStack(Stack** top) { *top = NULL; // 初始化为空链表,头指针为NULL } bool IsEmpty(Stack* top) { return top == NULL; } Stack* CreateNode(int data) { Stack* node = (Stack*)malloc(sizeof(Stack)); if (node == NULL) { printf("分配空间出现错误"); return NULL; } node->data = data; node->next = NULL; return node; } void Push(Stack** top, int data) { Stack* newnode = CreateNode(data); if (newnode == NULL) return; newnode->next = *top; *top = newnode; // 更新头指针指向新节点 } int Pop(Stack** top) { if (IsEmpty(*top)) { printf("栈已经空了不能出栈\n"); return -1; } Stack* temp = *top; int data = temp->data; *top = temp->next; // 更新头指针指向下一个节点 free(temp); return data; } void Println(Stack* top) { Stack* temp = top; while (temp != NULL) { printf("%d ", temp->data); temp = temp->next; } printf("\n"); } int main() { Stack* stack; InitStack(&stack); Push(&stack, 1); Push(&stack, 2); Push(&stack, 3); Push(&stack, 4); Println(stack); printf("出栈: %d\n", Pop(&stack)); printf("出栈: %d\n", Pop(&stack)); Println(stack); return 0; }
队列c语言实现 数组实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef struct stack { int data; struct stack* next; } Stack; void InitStack(Stack** top) { *top = NULL; // 初始化为空链表,头指针为NULL } bool IsEmpty(Stack* top) { return top == NULL; } Stack* CreateNode(int data) { Stack* node = (Stack*)malloc(sizeof(Stack)); if (node == NULL) { printf("分配空间出现错误"); return NULL; } node->data = data; node->next = NULL; return node; } void Push(Stack** top, int data) { Stack* newnode = CreateNode(data); if (newnode == NULL) return; newnode->next = *top; *top = newnode; // 更新头指针指向新节点 } int Pop(Stack** top) { if (IsEmpty(*top)) { printf("栈已经空了不能出栈\n"); return -1; } Stack* temp = *top; int data = temp->data; *top = temp->next; // 更新头指针指向下一个节点 free(temp); return data; } void Println(Stack* top) { Stack* temp = top; while (temp != NULL) { printf("%d ", temp->data); temp = temp->next; } printf("\n"); } int main() { Stack* stack; InitStack(&stack); Push(&stack, 1); Push(&stack, 2); Push(&stack, 3); Push(&stack, 4); Println(stack); printf("出栈: %d\n", Pop(&stack)); printf("出栈: %d\n", Pop(&stack)); Println(stack); return 0; }
哈希表c简单实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include<stdio.h> #include<stdlib.h> #define NUM 5 typedef struct HashList { int num; char data[NUM]; // 修改为字符数组 } HashList; HashList* initList() { HashList* list = (HashList*)malloc(sizeof(HashList)); list->num = 0; for (int i = 0; i < NUM; i++) { list->data[i] = 0; // 初始化所有元素为0 } return list; } // ASCII码计算自动计算 int hash(int data) { return data % NUM; } void put(HashList* list, char data) { int index = hash(data); printf("index = %d\n", index); // 发生冲突 while (list->data[index] != 0) { // 确保这个位置已经被占用 int count = 1; index = hash(index + 1); // 线性查找 count++; printf("index = %d\n", index); } list->data[index] = data; } int main() { HashList* list = initList(); put(list, 'A'); put(list, 'F'); for (int i = 0; i < NUM; i++) { if (list->data[i] != 0) { // 只打印已经使用的槽位 printf("%c\n", list->data[i]); } } return 0; }
借鉴: https://github.com/hunterhug/goa.c/blob/master/algorithm/dict.md
go实现可变数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 package mainimport ( "fmt" "sync" ) type Array struct { array []int len int cap int lock sync.Mutex } func Make (len , cap int ) *Array { s := new (Array) if len > cap { panic ("len large than cap" ) } array := make ([]int , cap , cap ) s.array = array s.cap = cap s.len = 0 return s } func (a *Array) Append(element int ) { a.lock.Lock() defer a.lock.Unlock() if a.len == a.cap { newCap := 2 * a.len if a.cap == 0 { newCap = 1 } newArray := make ([]int , newCap, newCap) for k, v := range a.array { newArray[k] = v } a.array = newArray a.cap = newCap } a.array[a.len ] = element a.len = a.len + 1 } func (a *Array) AppendMany(element ...int ) { for _, v := range element { a.Append(v) } } func (a *Array) Get(index int ) int { if a.len == 0 || index >= a.len { panic ("index over len" ) } return a.array[index] } func (a *Array) Len() int { return a.len } func (a *Array) Cap() int { return a.cap } func Print (array *Array) (result string ) { result = "[" for i := 0 ; i < array.Len(); i++ { if i == 0 { result = fmt.Sprintf("%s%d" , result, array.Get(i)) continue } result = fmt.Sprintf("%s %d" , result, array.Get(i)) } result = result + "]" return } func main () { a := Make(0 , 3 ) fmt.Println("cap" , a.Cap(), "len" , a.Len(), "array:" , Print(a)) a.Append(10 ) fmt.Println("cap" , a.Cap(), "len" , a.Len(), "array:" , Print(a)) a.Append(9 ) fmt.Println("cap" , a.Cap(), "len" , a.Len(), "array:" , Print(a)) a.AppendMany(8 , 7 ) fmt.Println("cap" , a.Cap(), "len" , a.Len(), "array:" , Print(a)) }
字典 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 package mainimport ( "fmt" "sync" "unsafe" ) type Set struct { m map [int ]struct {} len int sync.RWMutex } func NewSet (cap int64 ) *Set { temp := make (map [int ]struct {}, cap ) return &Set{ m: temp, } } func (s *Set) Add(item int ) { s.Lock() defer s.Unlock() s.m[item] = struct {}{} s.len = len (s.m) } func (s *Set) Remove(item int ) { s.Lock() defer s.Unlock() if s.len == 0 { return } delete (s.m, item) s.len = len (s.m) } func (s *Set) Has(item int ) bool { s.RLock() defer s.RUnlock() _, ok := s.m[item] return ok } func (s *Set) Len() int { return s.len } func (s *Set) Clear() { s.Lock() defer s.Unlock() s.m = map [int ]struct {}{} s.len = 0 } func (s *Set) IsEmpty() bool { if s.Len() == 0 { return true } return false } func (s *Set) List() []int { s.RLock() defer s.RUnlock() list := make ([]int , 0 , s.len ) for item := range s.m { list = append (list, item) } return list } func other () { a := struct {}{} b := struct {}{} if a == b { fmt.Printf("right:%p\n" , &a) } fmt.Println(unsafe.Sizeof(a)) } func main () { s := NewSet(5 ) s.Add(1 ) s.Add(1 ) s.Add(2 ) fmt.Println("list of all items" , s.List()) s.Clear() if s.IsEmpty() { fmt.Println("empty" ) } s.Add(1 ) s.Add(2 ) s.Add(3 ) if s.Has(2 ) { fmt.Println("2 does exist" ) } s.Remove(2 ) s.Remove(3 ) fmt.Println("list of all items" , s.List()) }
加并发锁,实现线程安全,然后往结构体 s *Set 里面的内置 map 添加该元素:item,元素作为字典的键,会自动去重。同时,集合大小重新生成。
s.m[item] = struct{}{} 这行代码向 m 这个映射中添加一个 item 作为键,并将其值设置为 struct{}{}。 由于 m 是 map[int]struct{} 类型的,它的键是 int 类型,而值是空结构体 struct{} 类型, 它们不占用任何空间。这一步实际上是往字典添加一个键,而不需要关心值。
最大堆的建立 堆排序中的(递归)是制造最大堆的关键 其实也可以不用最大堆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 #include <stdio.h> void heapsort (int a[],int length,int i) ;void buildheap (int a[], int length) ;void swap (int * a, int * b) ;void prinarry (int a[], int length) ;void prinarry (int a[], int length) { for (int i = 0 ; i < length; i++) { printf ("%d" , a[i]); } printf ("\n" ); } void swap (int * a, int * b) { int temp = 0 ; temp=*a; * a = *b; * b = temp; } void heapsort (int a[], int length, int i) { int largest = i; int left = 2 * i + 1 ; int right = 2 * i + 2 ; if (left<length && a[left]>a[largest]) { largest = left; } if (right<length && a[right]>a[largest]) { largest = right; } if (largest != i) { swap(&a[i], &a[largest]); heapsort(a, length, largest); } } void buildheap (int a[], int length) { int i = (length - 1 ) / 2 ; for (i=(length-1 )/2 ;i>=0 ;i--) { heapsort(a, length, i); } } int main () { int arry[6 ] = { 2 ,4 ,7 ,9 ,5 ,8 }; int length = sizeof (arry) / sizeof (arry[0 ]); buildheap(arry, length); prinarry(arry, length); return 0 ; }
好像不对劲 如果你期望的是排序后的数组(比如 120 100 90 50),你的代码缺少以下步骤:
交换堆顶和末尾元素:将最大堆的根节点(最大值)移动到数组末尾。 重新堆化剩余部分:对剩余的数组部分(即去掉最后一个元素的堆)重新堆化。 重复步骤:直到数组完全排序。
你的代码本身并没有严重的问题,但它仅仅完成了“构建最大堆”的功能,没有实现堆排序,因此输出的数组只是一个堆的结构(满足最大堆性质,但并非有序数组)。 如果你预期的结果是排序后的数组,那么确实还需要补充代码来完成堆排序的逻辑。
啊我靠
go实现最大堆 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 type Heap struct { Size int Array []int } func NewHeap (array []int ) *Heap { h := new (Heap) h.Array = array return h } func (h *Heap) Push(x int ) { if h.Size == 0 { h.Array[0 ] = x h.Size++ return } i := h.Size for i > 0 { parent := (i - 1 ) / 2 if x <= h.Array[parent] { break } h.Array[i] = h.Array[parent] i = parent } h.Array[i] = x h.Size++ } func (h *Heap) Pop() int { if h.Size == 0 { return -1 } ret := h.Array[0 ] h.Size-- x := h.Array[h.Size] h.Array[h.Size] = ret i := 0 for { a := 2 *i + 1 b := 2 *i + 2 if a >= h.Size { break } if b < h.Size && h.Array[b] > h.Array[a] { a = b } if x >= h.Array[a] { break } h.Array[i] = h.Array[a] i = a } h.Array[i] = x return ret }
这段代码太帅了 没有使用递归 用循环 构造了最大堆! 学习思想