问题描述
我正在尝试按升序对链接列表进行排序,并停留在此处。其余代码工作正常(追加,前置功能)。我试图在这里使用气泡排序算法。
void sortLinkedList(Node** head_ref)
{
Node* slow_node =(*head_ref);
Node* fast_node=NULL;
Node* temp=NULL;
while(slow_node->next!=NULL)
{
fast_node=slow_node->next;
while(fast_node->next!=NULL)
{
if(fast_node->data>fast_node->next->data)
{
temp->data=fast_node->data;
fast_node->data=fast_node->next->data;
fast_node->next->data=temp->data;
}
fast_node=fast_node->next;
}
slow_node=slow_node->next;
}
}
void printList(Node** head_ref)
{
Node* new_node=(*head_ref);
while(new_node!=NULL)
{
cout<<new_node->data<<"-->";
new_node=new_node->next;
}
cout<<"NULL";
cout<<endl;
}
int main()
{
Node* head=new Node();
head=NULL;
insertAtEnd(&head,2);
printList(&head);
insertAtEnd(&head,3);
printList(&head);
insertAtEnd(&head,2);
printList(&head);
insertAtEnd(&head,4);
printList(&head);
insertAtEnd(&head,5);
printList(&head);
cout<<"Sorted List"<<endl;
sortLinkedList(&head);
printList(&head);
}
2-->NULL
2-->3-->NULL
2-->3-->2-->NULL
2-->3-->2-->4-->NULL
2-->3-->2-->4-->5-->NULL
Sorted List
Segmentation fault (Core dumped)
解决方法
冒泡排序中的问题是交换操作。您使用临时(为NULL),并尝试访问数据元素。这会触发细分错误。
在最简单的情况下,您可以使用std::swap。您的气泡排序看起来像
// my swift variables in the ViewController
var vertexBuffer: MTLBuffer!
var renderPipelineState: MTLRenderPipelineState!
let sharedLibrary = sharedMetalRenderingDevice.device.makeDefaultLibrary()!
var _icbArgumentBuffer: MTLBuffer!
var _indirectCommandBuffer: MTLIndirectCommandBuffer!
var computePipelineState: MTLComputePipelineState!
// I call this inside viewDidLoad()
func setupMetalResources() {
guard let device = sceneView.device else {
assertionFailure()
return
}
struct TriangleVertex {
var position: vector_float3
}
let vertices: [TriangleVertex] = [
TriangleVertex(position: vector_float3( 0.0,0.5,1)),TriangleVertex(position: vector_float3( -0.5,-0.5,TriangleVertex(position: vector_float3( 0.5,1))
]
self.vertexBuffer = device.makeBuffer(
bytes: vertices,length: MemoryLayout<TriangleVertex>.size * vertices.count,options: .cpuCacheModeWriteCombined)
let vertexFunc = sharedLibrary.makeFunction(name: "passthrough_vertex")
let fragmentFunc = sharedLibrary.makeFunction(name: "passthrough_fragment")
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.vertexFunction = vertexFunc
pipelineDescriptor.fragmentFunction = fragmentFunc
pipelineDescriptor.colorAttachments[0].pixelFormat = sceneView.colorPixelFormat
pipelineDescriptor.depthAttachmentPixelFormat = sceneView.depthPixelFormat
pipelineDescriptor.supportIndirectCommandBuffers = true
guard let pipeline = try? device.makeRenderPipelineState(descriptor: pipelineDescriptor)
else {
assertionFailure()
return
}
self.renderPipelineState = pipeline
let cullF = sharedLibrary.makeFunction(name: "testCull")
let ag = cullF?.makeArgumentEncoder(bufferIndex: 1)
let icbDesc = MTLIndirectCommandBufferDescriptor()
icbDesc.commandTypes = .draw
icbDesc.inheritBuffers = false
icbDesc.maxVertexBufferBindCount = 3
icbDesc.maxFragmentBufferBindCount = 0
_indirectCommandBuffer = sharedMetalRenderingDevice.device.makeIndirectCommandBuffer(descriptor: icbDesc,maxCommandCount: 3,options: .storageModePrivate)
_icbArgumentBuffer = sharedMetalRenderingDevice.device.makeBuffer(length: ag!.encodedLength,options: .storageModeShared)
ag?.setArgumentBuffer(_icbArgumentBuffer,offset: 0)
ag?.setIndirectCommandBuffer(_indirectCommandBuffer,index: 0)
do {
computePipelineState = try sharedMetalRenderingDevice.device.makeComputePipelineState(function: t!)
} catch {
}
}
// This is the SCNSceneRendererDelegate’s -> didRenderScene of SceneKit (my sceneview)
func renderer(_ renderer: SCNSceneRenderer,didRenderScene scene: SCNScene,atTime time: TimeInterval) {
guard let renderEncoder = renderer.currentRenderCommandEncoder else { return }
let myRange: Range = 0..<65536
let commandBuffer = renderer.commandQueue?.makeCommandBuffer()
let blit = commandBuffer?.makeBlitCommandEncoder()
blit?.resetCommandsInBuffer(_indirectCommandBuffer,range: myRange)
blit?.endEncoding()
let computeEncoder = commandBuffer?.makeComputeCommandEncoder()
computeEncoder!.setComputePipelineState(computePipelineState!)
computeEncoder!.setBuffer(vertexBuffer,offset: 0,index: 0)
computeEncoder!.setBuffer(_icbArgumentBuffer,index: 1)
computeEncoder!.useResource( _indirectCommandBuffer,usage: .write)
computeEncoder!.dispatchThreads(MTLSize(width: 1,height: 1,depth: 1),threadsPerThreadgroup: MTLSize(width: 1,depth: 1))
computeEncoder!.endEncoding()
let optimBlit = commandBuffer?.makeBlitCommandEncoder()
optimBlit?.optimizeIndirectCommandBuffer(_indirectCommandBuffer,range: myRange)
optimBlit?.endEncoding()
renderEncoder.setCullMode(.back)
renderEncoder.setRenderPipelineState(renderPipelineState)
renderEncoder.useResource(vertexBuffer,usage: .read)
// If I comment the entire compute encoder and pass the vertex buffer to the render encoder,it works fine
// The below 2 lines are how I pass the vertex buffer into the render pass
// renderEncoder.setVertexBuffer(vertexBuffer,index: 0)
// renderEncoder.drawPrimitives(type: .triangle,vertexStart: 0,vertexCount: 3)
renderEncoder.executeCommandsInBuffer( _indirectCommandBuffer,range: myRange)
// renderEncoder.endEncoding() // uncommenting this causes "invalid usage because encoding has ended."
commandBuffer?.commit() // I get a GPU Hang error
// commandBuffer?.waitUntilCompleted() // uncommenting this causes the screen to go black and nothing shows
}
// This is the Metal shader code
struct Vertex
{
float4 position [[position]];
};
struct Vertex1
{
float3 position;
};
vertex Vertex passthrough_vertex(const device Vertex1 *vertices [[buffer(0)]],constant simd_float4x4& modelViewProjectionTransform [[buffer(1)]],uint vid [[vertex_id]])
{
Vertex out;
out.position = modelViewProjectionTransform * float4(vertices[vid].position,1);
// out.position = float4(vertices[vid].position.x,vertices[vid].position.y,vertices[vid].position.z,1);
return out;
}
fragment float4 passthrough_fragment(Vertex inVertex [[stage_in]])
{
return float4(1,1);
}
typedef struct ICBContainer
{
command_buffer commandBuffer [[ id(0) ]];
} ICBContainer;
kernel void
testCull(uint objectIndex [[ thread_position_in_grid ]],device Vertex1 *vertices [[ buffer(0) ]],device ICBContainer *icb_container [[ buffer(1) ]])
{
render_command cmd(icb_container->commandBuffer,objectIndex);
cmd.set_vertex_buffer(vertices,0);
cmd.draw_primitives(primitive_type::triangle,3,1,1);
}
,
你有
Node* temp=NULL;
然后是你
temp->data=fast_node->data;
并由于“ temp
是空指针”而变大。
如果您要交换节点的数据,则不需要整个节点,只需使用data
类型之一即可:
if(fast_node->data>fast_node->next->data)
{
whatever_data_is temp = fast_node->data;
fast_node->data = fast_node->next->data;
fast_node->next->data = temp;
}
但是标准库中已经有交换功能,因此您可以简化:
if (fast_node->data>fast_node->next->data)
{
std::swap(fast_node->data,fast_node->next->data);
}